LLVM  8.0.1
RuntimeDyldELFMips.cpp
Go to the documentation of this file.
1 //===-- RuntimeDyldELFMips.cpp ---- ELF/Mips specific code. -----*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "RuntimeDyldELFMips.h"
11 #include "llvm/BinaryFormat/ELF.h"
12 
13 #define DEBUG_TYPE "dyld"
14 
15 void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry &RE,
16  uint64_t Value) {
18  if (IsMipsO32ABI)
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);
26  else
27  llvm_unreachable("Mips ABI not handled");
28 }
29 
30 uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE,
31  uint64_t Value,
32  uint64_t Addend) {
33  if (IsMipsN32ABI) {
35  Value = evaluateMIPS64Relocation(Section, RE.Offset, Value, RE.RelType,
36  Addend, RE.SymOffset, RE.SectionID);
37  return Value;
38  }
39  llvm_unreachable("Not reachable");
40 }
41 
42 void RuntimeDyldELFMips::applyRelocation(const RelocationEntry &RE,
43  uint64_t Value) {
44  if (IsMipsN32ABI) {
46  applyMIPSRelocation(Section.getAddressWithOffset(RE.Offset), Value,
47  RE.RelType);
48  return;
49  }
50  llvm_unreachable("Not reachable");
51 }
52 
53 int64_t
54 RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry &Section,
55  uint64_t Offset, uint64_t Value,
56  uint32_t Type) {
57 
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");
64 
65  switch (Type) {
66  default:
67  llvm_unreachable("Unknown relocation type!");
68  return Value;
69  case ELF::R_MIPS_32:
70  return Value;
71  case ELF::R_MIPS_26:
72  return Value >> 2;
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:
77  return Value;
78  case ELF::R_MIPS_PC32: {
79  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
80  return Value - FinalAddress;
81  }
82  case ELF::R_MIPS_PC16: {
83  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
84  return (Value - FinalAddress) >> 2;
85  }
86  case ELF::R_MIPS_PC19_S2: {
87  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
88  return (Value - (FinalAddress & ~0x3)) >> 2;
89  }
90  case ELF::R_MIPS_PC21_S2: {
91  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
92  return (Value - FinalAddress) >> 2;
93  }
94  case ELF::R_MIPS_PC26_S2: {
95  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
96  return (Value - FinalAddress) >> 2;
97  }
98  case ELF::R_MIPS_PCHI16: {
99  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
100  return (Value - FinalAddress + 0x8000) >> 16;
101  }
102  case ELF::R_MIPS_PCLO16: {
103  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
104  return Value - FinalAddress;
105  }
106  }
107 }
108 
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) {
112 
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");
123 
124  switch (Type) {
125  default:
126  llvm_unreachable("Not implemented relocation type!");
127  break;
128  case ELF::R_MIPS_JALR:
129  case ELF::R_MIPS_NONE:
130  break;
131  case ELF::R_MIPS_32:
132  case ELF::R_MIPS_64:
133  return Value + Addend;
134  case ELF::R_MIPS_26:
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);
139  }
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());
157 
158  Value += Addend;
159  if (Type == ELF::R_MIPS_GOT_PAGE)
160  Value = (Value + 0x8000) & ~0xffff;
161 
162  if (GOTEntry)
163  assert(GOTEntry == Value &&
164  "GOT entry has two different addresses.");
165  else
166  writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize());
167 
168  return (SymOffset - 0x7ff0) & 0xffff;
169  }
170  case ELF::R_MIPS_GOT_OFST: {
171  int64_t page = (Value + Addend + 0x8000) & ~0xffff;
172  return (Value + Addend - page) & 0xffff;
173  }
174  case ELF::R_MIPS_GPREL32: {
175  uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
176  return Value + Addend - (GOTAddr + 0x7ff0);
177  }
178  case ELF::R_MIPS_PC16: {
179  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
180  return ((Value + Addend - FinalAddress) >> 2) & 0xffff;
181  }
182  case ELF::R_MIPS_PC32: {
183  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
184  return Value + Addend - FinalAddress;
185  }
186  case ELF::R_MIPS_PC18_S3: {
187  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
188  return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff;
189  }
190  case ELF::R_MIPS_PC19_S2: {
191  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
192  return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff;
193  }
194  case ELF::R_MIPS_PC21_S2: {
195  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
196  return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff;
197  }
198  case ELF::R_MIPS_PC26_S2: {
199  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
200  return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff;
201  }
202  case ELF::R_MIPS_PCHI16: {
203  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
204  return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff;
205  }
206  case ELF::R_MIPS_PCLO16: {
207  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
208  return (Value + Addend - FinalAddress) & 0xffff;
209  }
210  }
211  return 0;
212 }
213 
214 void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value,
215  uint32_t Type) {
216  uint32_t Insn = readBytesUnaligned(TargetPtr, 4);
217 
218  switch (Type) {
219  default:
220  llvm_unreachable("Unknown relocation type!");
221  break;
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);
236  break;
237  case ELF::R_MIPS_PC18_S3:
238  Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff);
239  writeBytesUnaligned(Insn, TargetPtr, 4);
240  break;
241  case ELF::R_MIPS_PC19_S2:
242  Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff);
243  writeBytesUnaligned(Insn, TargetPtr, 4);
244  break;
245  case ELF::R_MIPS_PC21_S2:
246  Insn = (Insn & 0xffe00000) | (Value & 0x001fffff);
247  writeBytesUnaligned(Insn, TargetPtr, 4);
248  break;
249  case ELF::R_MIPS_26:
250  case ELF::R_MIPS_PC26_S2:
251  Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff);
252  writeBytesUnaligned(Insn, TargetPtr, 4);
253  break;
254  case ELF::R_MIPS_32:
255  case ELF::R_MIPS_GPREL32:
256  case ELF::R_MIPS_PC32:
257  writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4);
258  break;
259  case ELF::R_MIPS_64:
260  case ELF::R_MIPS_SUB:
261  writeBytesUnaligned(Value, TargetPtr, 8);
262  break;
263  }
264 }
265 
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,
272  Type);
273 }
274 
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;
281 
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,
286  RelType, Addend,
287  SymOffset, SectionID);
288  if (r_type2 != ELF::R_MIPS_NONE) {
289  RelType = r_type2;
290  CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
291  CalculatedValue, SymOffset,
292  SectionID);
293  }
294  if (r_type3 != ELF::R_MIPS_NONE) {
295  RelType = r_type3;
296  CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
297  CalculatedValue, SymOffset,
298  SectionID);
299  }
300  applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
301  RelType);
302 }
303 
305  uint64_t Offset,
306  uint32_t Value, uint32_t Type,
307  int32_t Addend) {
308  uint8_t *TargetPtr = Section.getAddressWithOffset(Offset);
309  Value += Addend;
310 
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");
317 
318  Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);
319 
320  applyMIPSRelocation(TargetPtr, Value, Type);
321 }
RelocationEntry - used to represent relocations internally in the dynamic linker. ...
uint64_t readBytesUnaligned(uint8_t *Src, unsigned Size) const
Endian-aware read Read the least significant Size bytes from Src.
uint64_t getLoadAddressWithOffset(unsigned OffsetBytes) const
Return the load address of this section with an offset.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
size_t getGOTEntrySize() override
void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const
Endian-aware write.
unsigned SectionID
SectionID - the section this relocation points to.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
DenseMap< SID, SID > SectionToGOTMap
uint8_t * getSectionAddress(unsigned SectionID) const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
int64_t Addend
Addend - the relocation addend encoded in the instruction itself.
uint32_t RelType
RelType - relocation type.
uint64_t getSectionLoadAddress(unsigned SectionID) const
void resolveMIPSN32Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend, uint64_t SymOffset, SID SectionID)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
uint64_t Offset
Offset - offset into the section.
uint8_t * getAddressWithOffset(unsigned OffsetBytes) const
Return the address of this section with an offset.
void resolveMIPSN64Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend, uint64_t SymOffset, SID SectionID)
void resolveMIPSO32Relocation(const SectionEntry &Section, uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend)
SectionEntry - represents a section emitted into memory by the dynamic linker.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
#define LLVM_DEBUG(X)
Definition: Debug.h:123