1 //===-- RuntimeDyldELFMips.cpp ---- ELF/Mips specific code. -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "RuntimeDyldELFMips.h"
11 #include "llvm/BinaryFormat/ELF.h"
13 #define DEBUG_TYPE "dyld"
15 void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry &RE,
17 const SectionEntry &Section = Sections[RE.SectionID];
19 resolveMIPSO32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend);
20 else if (IsMipsN32ABI) {
21 resolveMIPSN32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
22 RE.SymOffset, RE.SectionID);
23 } else if (IsMipsN64ABI)
24 resolveMIPSN64Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
25 RE.SymOffset, RE.SectionID);
27 llvm_unreachable("Mips ABI not handled");
30 uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE,
34 const SectionEntry &Section = Sections[RE.SectionID];
35 Value = evaluateMIPS64Relocation(Section, RE.Offset, Value, RE.RelType,
36 Addend, RE.SymOffset, RE.SectionID);
39 llvm_unreachable("Not reachable");
42 void RuntimeDyldELFMips::applyRelocation(const RelocationEntry &RE,
45 const SectionEntry &Section = Sections[RE.SectionID];
46 applyMIPSRelocation(Section.getAddressWithOffset(RE.Offset), Value,
50 llvm_unreachable("Not reachable");
54 RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry &Section,
55 uint64_t Offset, uint64_t Value,
58 LLVM_DEBUG(dbgs() << "evaluateMIPS32Relocation, LocalAddress: 0x"
59 << format("%llx", Section.getAddressWithOffset(Offset))
60 << " FinalAddress: 0x"
61 << format("%llx", Section.getLoadAddressWithOffset(Offset))
62 << " Value: 0x" << format("%llx", Value) << " Type: 0x"
63 << format("%x", Type) << "\n");
67 llvm_unreachable("Unknown relocation type!");
73 case ELF::R_MIPS_HI16:
74 // Get the higher 16-bits. Also add 1 if bit 15 is 1.
75 return (Value + 0x8000) >> 16;
76 case ELF::R_MIPS_LO16:
78 case ELF::R_MIPS_PC32: {
79 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
80 return Value - FinalAddress;
82 case ELF::R_MIPS_PC16: {
83 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
84 return (Value - FinalAddress) >> 2;
86 case ELF::R_MIPS_PC19_S2: {
87 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
88 return (Value - (FinalAddress & ~0x3)) >> 2;
90 case ELF::R_MIPS_PC21_S2: {
91 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
92 return (Value - FinalAddress) >> 2;
94 case ELF::R_MIPS_PC26_S2: {
95 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
96 return (Value - FinalAddress) >> 2;
98 case ELF::R_MIPS_PCHI16: {
99 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
100 return (Value - FinalAddress + 0x8000) >> 16;
102 case ELF::R_MIPS_PCLO16: {
103 uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
104 return Value - FinalAddress;
109 int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(
110 const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
111 int64_t Addend, uint64_t SymOffset, SID SectionID) {
113 LLVM_DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x"
114 << format("%llx", Section.getAddressWithOffset(Offset))
115 << " FinalAddress: 0x"
116 << format("%llx", Section.getLoadAddressWithOffset(Offset))
117 << " Value: 0x" << format("%llx", Value) << " Type: 0x"
118 << format("%x", Type) << " Addend: 0x"
119 << format("%llx", Addend)
120 << " Offset: " << format("%llx" PRIx64, Offset)
121 << " SID: " << format("%d", SectionID)
122 << " SymOffset: " << format("%x", SymOffset) << "\n");
126 llvm_unreachable("Not implemented relocation type!");
128 case ELF::R_MIPS_JALR:
129 case ELF::R_MIPS_NONE:
133 return Value + Addend;
135 return ((Value + Addend) >> 2) & 0x3ffffff;
136 case ELF::R_MIPS_GPREL16: {
137 uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
138 return Value + Addend - (GOTAddr + 0x7ff0);
140 case ELF::R_MIPS_SUB:
141 return Value - Addend;
142 case ELF::R_MIPS_HI16:
143 // Get the higher 16-bits. Also add 1 if bit 15 is 1.
144 return ((Value + Addend + 0x8000) >> 16) & 0xffff;
145 case ELF::R_MIPS_LO16:
146 return (Value + Addend) & 0xffff;
147 case ELF::R_MIPS_HIGHER:
148 return ((Value + Addend + 0x80008000) >> 32) & 0xffff;
149 case ELF::R_MIPS_HIGHEST:
150 return ((Value + Addend + 0x800080008000) >> 48) & 0xffff;
151 case ELF::R_MIPS_CALL16:
152 case ELF::R_MIPS_GOT_DISP:
153 case ELF::R_MIPS_GOT_PAGE: {
154 uint8_t *LocalGOTAddr =
155 getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset;
156 uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, getGOTEntrySize());
159 if (Type == ELF::R_MIPS_GOT_PAGE)
160 Value = (Value + 0x8000) & ~0xffff;
163 assert(GOTEntry == Value &&
164 "GOT entry has two different addresses.");
166 writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize());
168 return (SymOffset - 0x7ff0) & 0xffff;
170 case ELF::R_MIPS_GOT_OFST: {
171 int64_t page = (Value + Addend + 0x8000) & ~0xffff;
172 return (Value + Addend - page) & 0xffff;
174 case ELF::R_MIPS_GPREL32: {
175 uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
176 return Value + Addend - (GOTAddr + 0x7ff0);
178 case ELF::R_MIPS_PC16: {
179 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
180 return ((Value + Addend - FinalAddress) >> 2) & 0xffff;
182 case ELF::R_MIPS_PC32: {
183 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
184 return Value + Addend - FinalAddress;
186 case ELF::R_MIPS_PC18_S3: {
187 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
188 return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff;
190 case ELF::R_MIPS_PC19_S2: {
191 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
192 return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff;
194 case ELF::R_MIPS_PC21_S2: {
195 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
196 return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff;
198 case ELF::R_MIPS_PC26_S2: {
199 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
200 return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff;
202 case ELF::R_MIPS_PCHI16: {
203 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
204 return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff;
206 case ELF::R_MIPS_PCLO16: {
207 uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
208 return (Value + Addend - FinalAddress) & 0xffff;
214 void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value,
216 uint32_t Insn = readBytesUnaligned(TargetPtr, 4);
220 llvm_unreachable("Unknown relocation type!");
222 case ELF::R_MIPS_GPREL16:
223 case ELF::R_MIPS_HI16:
224 case ELF::R_MIPS_LO16:
225 case ELF::R_MIPS_HIGHER:
226 case ELF::R_MIPS_HIGHEST:
227 case ELF::R_MIPS_PC16:
228 case ELF::R_MIPS_PCHI16:
229 case ELF::R_MIPS_PCLO16:
230 case ELF::R_MIPS_CALL16:
231 case ELF::R_MIPS_GOT_DISP:
232 case ELF::R_MIPS_GOT_PAGE:
233 case ELF::R_MIPS_GOT_OFST:
234 Insn = (Insn & 0xffff0000) | (Value & 0x0000ffff);
235 writeBytesUnaligned(Insn, TargetPtr, 4);
237 case ELF::R_MIPS_PC18_S3:
238 Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff);
239 writeBytesUnaligned(Insn, TargetPtr, 4);
241 case ELF::R_MIPS_PC19_S2:
242 Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff);
243 writeBytesUnaligned(Insn, TargetPtr, 4);
245 case ELF::R_MIPS_PC21_S2:
246 Insn = (Insn & 0xffe00000) | (Value & 0x001fffff);
247 writeBytesUnaligned(Insn, TargetPtr, 4);
250 case ELF::R_MIPS_PC26_S2:
251 Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff);
252 writeBytesUnaligned(Insn, TargetPtr, 4);
255 case ELF::R_MIPS_GPREL32:
256 case ELF::R_MIPS_PC32:
257 writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4);
260 case ELF::R_MIPS_SUB:
261 writeBytesUnaligned(Value, TargetPtr, 8);
266 void RuntimeDyldELFMips::resolveMIPSN32Relocation(
267 const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
268 int64_t Addend, uint64_t SymOffset, SID SectionID) {
269 int64_t CalculatedValue = evaluateMIPS64Relocation(
270 Section, Offset, Value, Type, Addend, SymOffset, SectionID);
271 applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
275 void RuntimeDyldELFMips::resolveMIPSN64Relocation(
276 const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
277 int64_t Addend, uint64_t SymOffset, SID SectionID) {
278 uint32_t r_type = Type & 0xff;
279 uint32_t r_type2 = (Type >> 8) & 0xff;
280 uint32_t r_type3 = (Type >> 16) & 0xff;
282 // RelType is used to keep information for which relocation type we are
283 // applying relocation.
284 uint32_t RelType = r_type;
285 int64_t CalculatedValue = evaluateMIPS64Relocation(Section, Offset, Value,
287 SymOffset, SectionID);
288 if (r_type2 != ELF::R_MIPS_NONE) {
290 CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
291 CalculatedValue, SymOffset,
294 if (r_type3 != ELF::R_MIPS_NONE) {
296 CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
297 CalculatedValue, SymOffset,
300 applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
304 void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section,
306 uint32_t Value, uint32_t Type,
308 uint8_t *TargetPtr = Section.getAddressWithOffset(Offset);
311 LLVM_DEBUG(dbgs() << "resolveMIPSO32Relocation, LocalAddress: "
312 << Section.getAddressWithOffset(Offset) << " FinalAddress: "
313 << format("%p", Section.getLoadAddressWithOffset(Offset))
314 << " Value: " << format("%x", Value) << " Type: "
315 << format("%x", Type) << " Addend: " << format("%x", Addend)
316 << " SymOffset: " << format("%x", Offset) << "\n");
318 Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);
320 applyMIPSRelocation(TargetPtr, Value, Type);