1 //===---- RuntimeDyldMachOI386.h ---- MachO/I386 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 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H
10 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H
12 #include "../RuntimeDyldMachO.h"
15 #define DEBUG_TYPE "dyld"
19 class RuntimeDyldMachOI386
20 : public RuntimeDyldMachOCRTPBase
<RuntimeDyldMachOI386
> {
23 typedef uint32_t TargetPtrT
;
25 RuntimeDyldMachOI386(RuntimeDyld::MemoryManager
&MM
,
26 JITSymbolResolver
&Resolver
)
27 : RuntimeDyldMachOCRTPBase(MM
, Resolver
) {}
29 unsigned getMaxStubSize() const override
{ return 0; }
31 unsigned getStubAlignment() override
{ return 1; }
33 Expected
<relocation_iterator
>
34 processRelocationRef(unsigned SectionID
, relocation_iterator RelI
,
35 const ObjectFile
&BaseObjT
,
36 ObjSectionToIDMap
&ObjSectionToID
,
37 StubMap
&Stubs
) override
{
38 const MachOObjectFile
&Obj
=
39 static_cast<const MachOObjectFile
&>(BaseObjT
);
40 MachO::any_relocation_info RelInfo
=
41 Obj
.getRelocation(RelI
->getRawDataRefImpl());
42 uint32_t RelType
= Obj
.getAnyRelocationType(RelInfo
);
44 if (Obj
.isRelocationScattered(RelInfo
)) {
45 if (RelType
== MachO::GENERIC_RELOC_SECTDIFF
||
46 RelType
== MachO::GENERIC_RELOC_LOCAL_SECTDIFF
)
47 return processSECTDIFFRelocation(SectionID
, RelI
, Obj
,
49 else if (RelType
== MachO::GENERIC_RELOC_VANILLA
)
50 return processScatteredVANILLA(SectionID
, RelI
, Obj
, ObjSectionToID
);
51 return make_error
<RuntimeDyldError
>(("Unhandled I386 scattered relocation "
52 "type: " + Twine(RelType
)).str());
56 UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PAIR
);
57 UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PB_LA_PTR
);
58 UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_TLV
);
60 if (RelType
> MachO::GENERIC_RELOC_TLV
)
61 return make_error
<RuntimeDyldError
>(("MachO I386 relocation type " +
63 " is out of range").str());
67 RelocationEntry
RE(getRelocationEntry(SectionID
, Obj
, RelI
));
68 RE
.Addend
= memcpyAddend(RE
);
69 RelocationValueRef Value
;
70 if (auto ValueOrErr
= getRelocationValueRef(Obj
, RelI
, RE
, ObjSectionToID
))
73 return ValueOrErr
.takeError();
75 // Addends for external, PC-rel relocations on i386 point back to the zero
76 // offset. Calculate the final offset from the relocation target instead.
77 // This allows us to use the same logic for both external and internal
78 // relocations in resolveI386RelocationRef.
79 // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
80 // if (IsExtern && RE.IsPCRel) {
81 // uint64_t RelocAddr = 0;
82 // RelI->getAddress(RelocAddr);
83 // Value.Addend += RelocAddr + 4;
86 makeValueAddendPCRel(Value
, RelI
, 1 << RE
.Size
);
88 RE
.Addend
= Value
.Offset
;
91 addRelocationForSymbol(RE
, Value
.SymbolName
);
93 addRelocationForSection(RE
, Value
.SectionID
);
98 void resolveRelocation(const RelocationEntry
&RE
, uint64_t Value
) override
{
99 LLVM_DEBUG(dumpRelocationToResolve(RE
, Value
));
101 const SectionEntry
&Section
= Sections
[RE
.SectionID
];
102 uint8_t *LocalAddress
= Section
.getAddressWithOffset(RE
.Offset
);
105 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(RE
.Offset
);
106 Value
-= FinalAddress
+ 4; // see MachOX86_64::resolveRelocation.
109 switch (RE
.RelType
) {
110 case MachO::GENERIC_RELOC_VANILLA
:
111 writeBytesUnaligned(Value
+ RE
.Addend
, LocalAddress
, 1 << RE
.Size
);
113 case MachO::GENERIC_RELOC_SECTDIFF
:
114 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF
: {
115 uint64_t SectionABase
= Sections
[RE
.Sections
.SectionA
].getLoadAddress();
116 uint64_t SectionBBase
= Sections
[RE
.Sections
.SectionB
].getLoadAddress();
117 assert((Value
== SectionABase
|| Value
== SectionBBase
) &&
118 "Unexpected SECTDIFF relocation value.");
119 Value
= SectionABase
- SectionBBase
+ RE
.Addend
;
120 writeBytesUnaligned(Value
, LocalAddress
, 1 << RE
.Size
);
124 llvm_unreachable("Invalid relocation type!");
128 Error
finalizeSection(const ObjectFile
&Obj
, unsigned SectionID
,
129 const SectionRef
&Section
) {
131 if (Expected
<StringRef
> NameOrErr
= Section
.getName())
134 consumeError(NameOrErr
.takeError());
136 if (Name
== "__jump_table")
137 return populateJumpTable(cast
<MachOObjectFile
>(Obj
), Section
, SectionID
);
138 else if (Name
== "__pointers")
139 return populateIndirectSymbolPointersSection(cast
<MachOObjectFile
>(Obj
),
141 return Error::success();
145 Expected
<relocation_iterator
>
146 processSECTDIFFRelocation(unsigned SectionID
, relocation_iterator RelI
,
147 const ObjectFile
&BaseObjT
,
148 ObjSectionToIDMap
&ObjSectionToID
) {
149 const MachOObjectFile
&Obj
=
150 static_cast<const MachOObjectFile
&>(BaseObjT
);
151 MachO::any_relocation_info RE
=
152 Obj
.getRelocation(RelI
->getRawDataRefImpl());
154 SectionEntry
&Section
= Sections
[SectionID
];
155 uint32_t RelocType
= Obj
.getAnyRelocationType(RE
);
156 bool IsPCRel
= Obj
.getAnyRelocationPCRel(RE
);
157 unsigned Size
= Obj
.getAnyRelocationLength(RE
);
158 uint64_t Offset
= RelI
->getOffset();
159 uint8_t *LocalAddress
= Section
.getAddressWithOffset(Offset
);
160 unsigned NumBytes
= 1 << Size
;
161 uint64_t Addend
= readBytesUnaligned(LocalAddress
, NumBytes
);
164 MachO::any_relocation_info RE2
=
165 Obj
.getRelocation(RelI
->getRawDataRefImpl());
167 uint32_t AddrA
= Obj
.getScatteredRelocationValue(RE
);
168 section_iterator SAI
= getSectionByAddress(Obj
, AddrA
);
169 assert(SAI
!= Obj
.section_end() && "Can't find section for address A");
170 uint64_t SectionABase
= SAI
->getAddress();
171 uint64_t SectionAOffset
= AddrA
- SectionABase
;
172 SectionRef SectionA
= *SAI
;
173 bool IsCode
= SectionA
.isText();
174 uint32_t SectionAID
= ~0U;
175 if (auto SectionAIDOrErr
=
176 findOrEmitSection(Obj
, SectionA
, IsCode
, ObjSectionToID
))
177 SectionAID
= *SectionAIDOrErr
;
179 return SectionAIDOrErr
.takeError();
181 uint32_t AddrB
= Obj
.getScatteredRelocationValue(RE2
);
182 section_iterator SBI
= getSectionByAddress(Obj
, AddrB
);
183 assert(SBI
!= Obj
.section_end() && "Can't find section for address B");
184 uint64_t SectionBBase
= SBI
->getAddress();
185 uint64_t SectionBOffset
= AddrB
- SectionBBase
;
186 SectionRef SectionB
= *SBI
;
187 uint32_t SectionBID
= ~0U;
188 if (auto SectionBIDOrErr
=
189 findOrEmitSection(Obj
, SectionB
, IsCode
, ObjSectionToID
))
190 SectionBID
= *SectionBIDOrErr
;
192 return SectionBIDOrErr
.takeError();
194 // Compute the addend 'C' from the original expression 'A - B + C'.
195 Addend
-= AddrA
- AddrB
;
197 LLVM_DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA
198 << ", AddrB: " << AddrB
<< ", Addend: " << Addend
199 << ", SectionA ID: " << SectionAID
<< ", SectionAOffset: "
200 << SectionAOffset
<< ", SectionB ID: " << SectionBID
201 << ", SectionBOffset: " << SectionBOffset
<< "\n");
202 RelocationEntry
R(SectionID
, Offset
, RelocType
, Addend
, SectionAID
,
203 SectionAOffset
, SectionBID
, SectionBOffset
,
206 addRelocationForSection(R
, SectionAID
);
211 // Populate stubs in __jump_table section.
212 Error
populateJumpTable(const MachOObjectFile
&Obj
,
213 const SectionRef
&JTSection
,
214 unsigned JTSectionID
) {
215 MachO::dysymtab_command DySymTabCmd
= Obj
.getDysymtabLoadCommand();
216 MachO::section Sec32
= Obj
.getSection(JTSection
.getRawDataRefImpl());
217 uint32_t JTSectionSize
= Sec32
.size
;
218 unsigned FirstIndirectSymbol
= Sec32
.reserved1
;
219 unsigned JTEntrySize
= Sec32
.reserved2
;
220 unsigned NumJTEntries
= JTSectionSize
/ JTEntrySize
;
221 uint8_t *JTSectionAddr
= getSectionAddress(JTSectionID
);
222 unsigned JTEntryOffset
= 0;
224 if (JTSectionSize
% JTEntrySize
!= 0)
225 return make_error
<RuntimeDyldError
>("Jump-table section does not contain "
226 "a whole number of stubs?");
228 for (unsigned i
= 0; i
< NumJTEntries
; ++i
) {
229 unsigned SymbolIndex
=
230 Obj
.getIndirectSymbolTableEntry(DySymTabCmd
, FirstIndirectSymbol
+ i
);
231 symbol_iterator SI
= Obj
.getSymbolByIndex(SymbolIndex
);
232 Expected
<StringRef
> IndirectSymbolName
= SI
->getName();
233 if (!IndirectSymbolName
)
234 return IndirectSymbolName
.takeError();
235 uint8_t *JTEntryAddr
= JTSectionAddr
+ JTEntryOffset
;
236 createStubFunction(JTEntryAddr
);
237 RelocationEntry
RE(JTSectionID
, JTEntryOffset
+ 1,
238 MachO::GENERIC_RELOC_VANILLA
, 0, true, 2);
239 addRelocationForSymbol(RE
, *IndirectSymbolName
);
240 JTEntryOffset
+= JTEntrySize
;
243 return Error::success();