LLVM  10.0.0svn
RuntimeDyldELFMips.cpp
Go to the documentation of this file.
1 //===-- RuntimeDyldELFMips.cpp ---- ELF/Mips specific code. -----*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "RuntimeDyldELFMips.h"
10 #include "llvm/BinaryFormat/ELF.h"
11 
12 #define DEBUG_TYPE "dyld"
13 
14 void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry &RE,
15  uint64_t Value) {
17  if (IsMipsO32ABI)
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);
25  else
26  llvm_unreachable("Mips ABI not handled");
27 }
28 
29 uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE,
30  uint64_t Value,
31  uint64_t Addend) {
32  if (IsMipsN32ABI) {
34  Value = evaluateMIPS64Relocation(Section, RE.Offset, Value, RE.RelType,
35  Addend, RE.SymOffset, RE.SectionID);
36  return Value;
37  }
38  llvm_unreachable("Not reachable");
39 }
40 
41 void RuntimeDyldELFMips::applyRelocation(const RelocationEntry &RE,
42  uint64_t Value) {
43  if (IsMipsN32ABI) {
45  applyMIPSRelocation(Section.getAddressWithOffset(RE.Offset), Value,
46  RE.RelType);
47  return;
48  }
49  llvm_unreachable("Not reachable");
50 }
51 
52 int64_t
53 RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry &Section,
54  uint64_t Offset, uint64_t Value,
55  uint32_t Type) {
56 
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");
63 
64  switch (Type) {
65  default:
66  llvm_unreachable("Unknown relocation type!");
67  return Value;
68  case ELF::R_MIPS_32:
69  return Value;
70  case ELF::R_MIPS_26:
71  return Value >> 2;
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:
76  return Value;
77  case ELF::R_MIPS_PC32: {
78  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
79  return Value - FinalAddress;
80  }
81  case ELF::R_MIPS_PC16: {
82  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
83  return (Value - FinalAddress) >> 2;
84  }
85  case ELF::R_MIPS_PC19_S2: {
86  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
87  return (Value - (FinalAddress & ~0x3)) >> 2;
88  }
89  case ELF::R_MIPS_PC21_S2: {
90  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
91  return (Value - FinalAddress) >> 2;
92  }
93  case ELF::R_MIPS_PC26_S2: {
94  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
95  return (Value - FinalAddress) >> 2;
96  }
97  case ELF::R_MIPS_PCHI16: {
98  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
99  return (Value - FinalAddress + 0x8000) >> 16;
100  }
101  case ELF::R_MIPS_PCLO16: {
102  uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
103  return Value - FinalAddress;
104  }
105  }
106 }
107 
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) {
111 
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");
122 
123  switch (Type) {
124  default:
125  llvm_unreachable("Not implemented relocation type!");
126  break;
127  case ELF::R_MIPS_JALR:
128  case ELF::R_MIPS_NONE:
129  break;
130  case ELF::R_MIPS_32:
131  case ELF::R_MIPS_64:
132  return Value + Addend;
133  case ELF::R_MIPS_26:
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);
138  }
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());
156 
157  Value += Addend;
158  if (Type == ELF::R_MIPS_GOT_PAGE)
159  Value = (Value + 0x8000) & ~0xffff;
160 
161  if (GOTEntry)
162  assert(GOTEntry == Value &&
163  "GOT entry has two different addresses.");
164  else
165  writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize());
166 
167  return (SymOffset - 0x7ff0) & 0xffff;
168  }
169  case ELF::R_MIPS_GOT_OFST: {
170  int64_t page = (Value + Addend + 0x8000) & ~0xffff;
171  return (Value + Addend - page) & 0xffff;
172  }
173  case ELF::R_MIPS_GPREL32: {
174  uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
175  return Value + Addend - (GOTAddr + 0x7ff0);
176  }
177  case ELF::R_MIPS_PC16: {
178  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
179  return ((Value + Addend - FinalAddress) >> 2) & 0xffff;
180  }
181  case ELF::R_MIPS_PC32: {
182  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
183  return Value + Addend - FinalAddress;
184  }
185  case ELF::R_MIPS_PC18_S3: {
186  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
187  return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff;
188  }
189  case ELF::R_MIPS_PC19_S2: {
190  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
191  return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff;
192  }
193  case ELF::R_MIPS_PC21_S2: {
194  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
195  return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff;
196  }
197  case ELF::R_MIPS_PC26_S2: {
198  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
199  return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff;
200  }
201  case ELF::R_MIPS_PCHI16: {
202  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
203  return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff;
204  }
205  case ELF::R_MIPS_PCLO16: {
206  uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
207  return (Value + Addend - FinalAddress) & 0xffff;
208  }
209  }
210  return 0;
211 }
212 
213 void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value,
214  uint32_t Type) {
215  uint32_t Insn = readBytesUnaligned(TargetPtr, 4);
216 
217  switch (Type) {
218  default:
219  llvm_unreachable("Unknown relocation type!");
220  break;
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);
235  break;
236  case ELF::R_MIPS_PC18_S3:
237  Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff);
238  writeBytesUnaligned(Insn, TargetPtr, 4);
239  break;
240  case ELF::R_MIPS_PC19_S2:
241  Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff);
242  writeBytesUnaligned(Insn, TargetPtr, 4);
243  break;
244  case ELF::R_MIPS_PC21_S2:
245  Insn = (Insn & 0xffe00000) | (Value & 0x001fffff);
246  writeBytesUnaligned(Insn, TargetPtr, 4);
247  break;
248  case ELF::R_MIPS_26:
249  case ELF::R_MIPS_PC26_S2:
250  Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff);
251  writeBytesUnaligned(Insn, TargetPtr, 4);
252  break;
253  case ELF::R_MIPS_32:
254  case ELF::R_MIPS_GPREL32:
255  case ELF::R_MIPS_PC32:
256  writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4);
257  break;
258  case ELF::R_MIPS_64:
259  case ELF::R_MIPS_SUB:
260  writeBytesUnaligned(Value, TargetPtr, 8);
261  break;
262  }
263 }
264 
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,
271  Type);
272 }
273 
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;
280 
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,
285  RelType, Addend,
286  SymOffset, SectionID);
287  if (r_type2 != ELF::R_MIPS_NONE) {
288  RelType = r_type2;
289  CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
290  CalculatedValue, SymOffset,
291  SectionID);
292  }
293  if (r_type3 != ELF::R_MIPS_NONE) {
294  RelType = r_type3;
295  CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
296  CalculatedValue, SymOffset,
297  SectionID);
298  }
299  applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
300  RelType);
301 }
302 
304  uint64_t Offset,
305  uint32_t Value, uint32_t Type,
306  int32_t Addend) {
307  uint8_t *TargetPtr = Section.getAddressWithOffset(Offset);
308  Value += Addend;
309 
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");
316 
317  Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);
318 
319  applyMIPSRelocation(TargetPtr, Value, Type);
320 }
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:123
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:45
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:132
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:72
#define LLVM_DEBUG(X)
Definition: Debug.h:122