1 //===-- RuntimeDyldELFMips.cpp ---- ELF/Mips specific code. -----*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "RuntimeDyldELFMips.h"
10 #include "llvm/BinaryFormat/ELF.h"
12 #define DEBUG_TYPE "dyld"
14 void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry
&RE
,
16 const SectionEntry
&Section
= Sections
[RE
.SectionID
];
18 resolveMIPSO32Relocation(Section
, RE
.Offset
, Value
, RE
.RelType
, RE
.Addend
);
19 else if (IsMipsN32ABI
) {
20 resolveMIPSN32Relocation(Section
, RE
.Offset
, Value
, RE
.RelType
, RE
.Addend
,
21 RE
.SymOffset
, RE
.SectionID
);
22 } else if (IsMipsN64ABI
)
23 resolveMIPSN64Relocation(Section
, RE
.Offset
, Value
, RE
.RelType
, RE
.Addend
,
24 RE
.SymOffset
, RE
.SectionID
);
26 llvm_unreachable("Mips ABI not handled");
29 uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry
&RE
,
33 const SectionEntry
&Section
= Sections
[RE
.SectionID
];
34 Value
= evaluateMIPS64Relocation(Section
, RE
.Offset
, Value
, RE
.RelType
,
35 Addend
, RE
.SymOffset
, RE
.SectionID
);
38 llvm_unreachable("Not reachable");
41 void RuntimeDyldELFMips::applyRelocation(const RelocationEntry
&RE
,
44 const SectionEntry
&Section
= Sections
[RE
.SectionID
];
45 applyMIPSRelocation(Section
.getAddressWithOffset(RE
.Offset
), Value
,
49 llvm_unreachable("Not reachable");
53 RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry
&Section
,
54 uint64_t Offset
, uint64_t Value
,
57 LLVM_DEBUG(dbgs() << "evaluateMIPS32Relocation, LocalAddress: 0x"
58 << format("%llx", Section
.getAddressWithOffset(Offset
))
59 << " FinalAddress: 0x"
60 << format("%llx", Section
.getLoadAddressWithOffset(Offset
))
61 << " Value: 0x" << format("%llx", Value
) << " Type: 0x"
62 << format("%x", Type
) << "\n");
66 llvm_unreachable("Unknown relocation type!");
72 case ELF::R_MIPS_HI16
:
73 // Get the higher 16-bits. Also add 1 if bit 15 is 1.
74 return (Value
+ 0x8000) >> 16;
75 case ELF::R_MIPS_LO16
:
77 case ELF::R_MIPS_PC32
: {
78 uint32_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
79 return Value
- FinalAddress
;
81 case ELF::R_MIPS_PC16
: {
82 uint32_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
83 return (Value
- FinalAddress
) >> 2;
85 case ELF::R_MIPS_PC19_S2
: {
86 uint32_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
87 return (Value
- (FinalAddress
& ~0x3)) >> 2;
89 case ELF::R_MIPS_PC21_S2
: {
90 uint32_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
91 return (Value
- FinalAddress
) >> 2;
93 case ELF::R_MIPS_PC26_S2
: {
94 uint32_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
95 return (Value
- FinalAddress
) >> 2;
97 case ELF::R_MIPS_PCHI16
: {
98 uint32_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
99 return (Value
- FinalAddress
+ 0x8000) >> 16;
101 case ELF::R_MIPS_PCLO16
: {
102 uint32_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
103 return Value
- FinalAddress
;
108 int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(
109 const SectionEntry
&Section
, uint64_t Offset
, uint64_t Value
, uint32_t Type
,
110 int64_t Addend
, uint64_t SymOffset
, SID SectionID
) {
112 LLVM_DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x"
113 << format("%llx", Section
.getAddressWithOffset(Offset
))
114 << " FinalAddress: 0x"
115 << format("%llx", Section
.getLoadAddressWithOffset(Offset
))
116 << " Value: 0x" << format("%llx", Value
) << " Type: 0x"
117 << format("%x", Type
) << " Addend: 0x"
118 << format("%llx", Addend
)
119 << " Offset: " << format("%llx" PRIx64
, Offset
)
120 << " SID: " << format("%d", SectionID
)
121 << " SymOffset: " << format("%x", SymOffset
) << "\n");
125 llvm_unreachable("Not implemented relocation type!");
127 case ELF::R_MIPS_JALR
:
128 case ELF::R_MIPS_NONE
:
132 return Value
+ Addend
;
134 return ((Value
+ Addend
) >> 2) & 0x3ffffff;
135 case ELF::R_MIPS_GPREL16
: {
136 uint64_t GOTAddr
= getSectionLoadAddress(SectionToGOTMap
[SectionID
]);
137 return Value
+ Addend
- (GOTAddr
+ 0x7ff0);
139 case ELF::R_MIPS_SUB
:
140 return Value
- Addend
;
141 case ELF::R_MIPS_HI16
:
142 // Get the higher 16-bits. Also add 1 if bit 15 is 1.
143 return ((Value
+ Addend
+ 0x8000) >> 16) & 0xffff;
144 case ELF::R_MIPS_LO16
:
145 return (Value
+ Addend
) & 0xffff;
146 case ELF::R_MIPS_HIGHER
:
147 return ((Value
+ Addend
+ 0x80008000) >> 32) & 0xffff;
148 case ELF::R_MIPS_HIGHEST
:
149 return ((Value
+ Addend
+ 0x800080008000) >> 48) & 0xffff;
150 case ELF::R_MIPS_CALL16
:
151 case ELF::R_MIPS_GOT_DISP
:
152 case ELF::R_MIPS_GOT_PAGE
: {
153 uint8_t *LocalGOTAddr
=
154 getSectionAddress(SectionToGOTMap
[SectionID
]) + SymOffset
;
155 uint64_t GOTEntry
= readBytesUnaligned(LocalGOTAddr
, getGOTEntrySize());
158 if (Type
== ELF::R_MIPS_GOT_PAGE
)
159 Value
= (Value
+ 0x8000) & ~0xffff;
162 assert(GOTEntry
== Value
&&
163 "GOT entry has two different addresses.");
165 writeBytesUnaligned(Value
, LocalGOTAddr
, getGOTEntrySize());
167 return (SymOffset
- 0x7ff0) & 0xffff;
169 case ELF::R_MIPS_GOT_OFST
: {
170 int64_t page
= (Value
+ Addend
+ 0x8000) & ~0xffff;
171 return (Value
+ Addend
- page
) & 0xffff;
173 case ELF::R_MIPS_GPREL32
: {
174 uint64_t GOTAddr
= getSectionLoadAddress(SectionToGOTMap
[SectionID
]);
175 return Value
+ Addend
- (GOTAddr
+ 0x7ff0);
177 case ELF::R_MIPS_PC16
: {
178 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
179 return ((Value
+ Addend
- FinalAddress
) >> 2) & 0xffff;
181 case ELF::R_MIPS_PC32
: {
182 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
183 return Value
+ Addend
- FinalAddress
;
185 case ELF::R_MIPS_PC18_S3
: {
186 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
187 return ((Value
+ Addend
- (FinalAddress
& ~0x7)) >> 3) & 0x3ffff;
189 case ELF::R_MIPS_PC19_S2
: {
190 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
191 return ((Value
+ Addend
- (FinalAddress
& ~0x3)) >> 2) & 0x7ffff;
193 case ELF::R_MIPS_PC21_S2
: {
194 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
195 return ((Value
+ Addend
- FinalAddress
) >> 2) & 0x1fffff;
197 case ELF::R_MIPS_PC26_S2
: {
198 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
199 return ((Value
+ Addend
- FinalAddress
) >> 2) & 0x3ffffff;
201 case ELF::R_MIPS_PCHI16
: {
202 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
203 return ((Value
+ Addend
- FinalAddress
+ 0x8000) >> 16) & 0xffff;
205 case ELF::R_MIPS_PCLO16
: {
206 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(Offset
);
207 return (Value
+ Addend
- FinalAddress
) & 0xffff;
213 void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr
, int64_t Value
,
215 uint32_t Insn
= readBytesUnaligned(TargetPtr
, 4);
219 llvm_unreachable("Unknown relocation type!");
221 case ELF::R_MIPS_GPREL16
:
222 case ELF::R_MIPS_HI16
:
223 case ELF::R_MIPS_LO16
:
224 case ELF::R_MIPS_HIGHER
:
225 case ELF::R_MIPS_HIGHEST
:
226 case ELF::R_MIPS_PC16
:
227 case ELF::R_MIPS_PCHI16
:
228 case ELF::R_MIPS_PCLO16
:
229 case ELF::R_MIPS_CALL16
:
230 case ELF::R_MIPS_GOT_DISP
:
231 case ELF::R_MIPS_GOT_PAGE
:
232 case ELF::R_MIPS_GOT_OFST
:
233 Insn
= (Insn
& 0xffff0000) | (Value
& 0x0000ffff);
234 writeBytesUnaligned(Insn
, TargetPtr
, 4);
236 case ELF::R_MIPS_PC18_S3
:
237 Insn
= (Insn
& 0xfffc0000) | (Value
& 0x0003ffff);
238 writeBytesUnaligned(Insn
, TargetPtr
, 4);
240 case ELF::R_MIPS_PC19_S2
:
241 Insn
= (Insn
& 0xfff80000) | (Value
& 0x0007ffff);
242 writeBytesUnaligned(Insn
, TargetPtr
, 4);
244 case ELF::R_MIPS_PC21_S2
:
245 Insn
= (Insn
& 0xffe00000) | (Value
& 0x001fffff);
246 writeBytesUnaligned(Insn
, TargetPtr
, 4);
249 case ELF::R_MIPS_PC26_S2
:
250 Insn
= (Insn
& 0xfc000000) | (Value
& 0x03ffffff);
251 writeBytesUnaligned(Insn
, TargetPtr
, 4);
254 case ELF::R_MIPS_GPREL32
:
255 case ELF::R_MIPS_PC32
:
256 writeBytesUnaligned(Value
& 0xffffffff, TargetPtr
, 4);
259 case ELF::R_MIPS_SUB
:
260 writeBytesUnaligned(Value
, TargetPtr
, 8);
265 void RuntimeDyldELFMips::resolveMIPSN32Relocation(
266 const SectionEntry
&Section
, uint64_t Offset
, uint64_t Value
, uint32_t Type
,
267 int64_t Addend
, uint64_t SymOffset
, SID SectionID
) {
268 int64_t CalculatedValue
= evaluateMIPS64Relocation(
269 Section
, Offset
, Value
, Type
, Addend
, SymOffset
, SectionID
);
270 applyMIPSRelocation(Section
.getAddressWithOffset(Offset
), CalculatedValue
,
274 void RuntimeDyldELFMips::resolveMIPSN64Relocation(
275 const SectionEntry
&Section
, uint64_t Offset
, uint64_t Value
, uint32_t Type
,
276 int64_t Addend
, uint64_t SymOffset
, SID SectionID
) {
277 uint32_t r_type
= Type
& 0xff;
278 uint32_t r_type2
= (Type
>> 8) & 0xff;
279 uint32_t r_type3
= (Type
>> 16) & 0xff;
281 // RelType is used to keep information for which relocation type we are
282 // applying relocation.
283 uint32_t RelType
= r_type
;
284 int64_t CalculatedValue
= evaluateMIPS64Relocation(Section
, Offset
, Value
,
286 SymOffset
, SectionID
);
287 if (r_type2
!= ELF::R_MIPS_NONE
) {
289 CalculatedValue
= evaluateMIPS64Relocation(Section
, Offset
, 0, RelType
,
290 CalculatedValue
, SymOffset
,
293 if (r_type3
!= ELF::R_MIPS_NONE
) {
295 CalculatedValue
= evaluateMIPS64Relocation(Section
, Offset
, 0, RelType
,
296 CalculatedValue
, SymOffset
,
299 applyMIPSRelocation(Section
.getAddressWithOffset(Offset
), CalculatedValue
,
303 void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry
&Section
,
305 uint32_t Value
, uint32_t Type
,
307 uint8_t *TargetPtr
= Section
.getAddressWithOffset(Offset
);
310 LLVM_DEBUG(dbgs() << "resolveMIPSO32Relocation, LocalAddress: "
311 << Section
.getAddressWithOffset(Offset
) << " FinalAddress: "
312 << format("%p", Section
.getLoadAddressWithOffset(Offset
))
313 << " Value: " << format("%x", Value
) << " Type: "
314 << format("%x", Type
) << " Addend: " << format("%x", Addend
)
315 << " SymOffset: " << format("%x", Offset
) << "\n");
317 Value
= evaluateMIPS32Relocation(Section
, Offset
, Value
, Type
);
319 applyMIPSRelocation(TargetPtr
, Value
, Type
);