LLVM  14.0.0git
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 
15  uint64_t Value) {
17  if (IsMipsO32ABI)
19  else if (IsMipsN32ABI) {
21  RE.SymOffset, RE.SectionID);
22  } else if (IsMipsN64ABI)
24  RE.SymOffset, RE.SectionID);
25  else
26  llvm_unreachable("Mips ABI not handled");
27 }
28 
29 uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE,
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,
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(
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 
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 
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 
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 }
llvm::RuntimeDyldImpl::Sections
SectionList Sections
Definition: RuntimeDyldImpl.h:254
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::RuntimeDyldELFMips::resolveMIPSN32Relocation
void resolveMIPSN32Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend, uint64_t SymOffset, SID SectionID)
Definition: RuntimeDyldELFMips.cpp:265
llvm::RuntimeDyldImpl::IsMipsO32ABI
bool IsMipsO32ABI
Definition: RuntimeDyldImpl.h:290
llvm::RelocationEntry::SymOffset
uint64_t SymOffset
Definition: RuntimeDyldImpl.h:140
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::RelocationEntry::SectionID
unsigned SectionID
SectionID - the section this relocation points to.
Definition: RuntimeDyldImpl.h:120
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:78
llvm::RelocationEntry::Offset
uint64_t Offset
Offset - offset into the section.
Definition: RuntimeDyldImpl.h:123
x3
In x86 we generate this spiffy xmm0 xmm0 ret in x86 we generate this which could be xmm1 movss xmm1 xmm0 ret In sse4 we could use insertps to make both better Here s another testcase that could use x3
Definition: README-SSE.txt:547
ELF.h
llvm::RuntimeDyldImpl::SID
unsigned SID
Definition: RuntimeDyldImpl.h:256
llvm::RuntimeDyldImpl::IsMipsN64ABI
bool IsMipsN64ABI
Definition: RuntimeDyldImpl.h:292
llvm::RuntimeDyldImpl::getSectionAddress
uint8_t * getSectionAddress(unsigned SectionID) const
Definition: RuntimeDyldImpl.h:471
llvm::RuntimeDyldELFMips::resolveMIPSN64Relocation
void resolveMIPSN64Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend, uint64_t SymOffset, SID SectionID)
Definition: RuntimeDyldELFMips.cpp:274
llvm::RuntimeDyldImpl::writeBytesUnaligned
void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const
Endian-aware write.
Definition: RuntimeDyld.cpp:721
llvm::RuntimeDyldImpl::getSectionLoadAddress
uint64_t getSectionLoadAddress(unsigned SectionID) const
Definition: RuntimeDyldImpl.h:464
llvm::RelocationEntry::Addend
int64_t Addend
Addend - the relocation addend encoded in the instruction itself.
Definition: RuntimeDyldImpl.h:130
llvm::RelocationEntry
RelocationEntry - used to represent relocations internally in the dynamic linker.
Definition: RuntimeDyldImpl.h:117
RuntimeDyldELFMips.h
uint64_t
llvm::SectionEntry
SectionEntry - represents a section emitted into memory by the dynamic linker.
Definition: RuntimeDyldImpl.h:45
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::RuntimeDyldImpl::IsMipsN32ABI
bool IsMipsN32ABI
Definition: RuntimeDyldImpl.h:291
llvm::RuntimeDyldELFMips::resolveMIPSO32Relocation
void resolveMIPSO32Relocation(const SectionEntry &Section, uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend)
Definition: RuntimeDyldELFMips.cpp:303
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
uint32_t
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::RuntimeDyldELF::getGOTEntrySize
size_t getGOTEntrySize() override
Definition: RuntimeDyldELF.cpp:2204
Insn
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
Definition: AArch64MIPeepholeOpt.cpp:74
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::RuntimeDyldELF::SectionToGOTMap
DenseMap< SID, SID > SectionToGOTMap
Definition: RuntimeDyldELF.h:143
llvm::RuntimeDyldImpl::readBytesUnaligned
uint64_t readBytesUnaligned(uint8_t *Src, unsigned Size) const
Endian-aware read Read the least significant Size bytes from Src.
Definition: RuntimeDyld.cpp:707
page
The object format emitted by the WebAssembly backed is documented see the home page
Definition: README.txt:16
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::RelocationEntry::RelType
uint32_t RelType
RelType - relocation type.
Definition: RuntimeDyldImpl.h:126
llvm::object::resolveRelocation
uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R, uint64_t S, uint64_t LocData)
Definition: RelocationResolver.cpp:736