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 Section
.getName(Name
);
133 if (Name
== "__jump_table")
134 return populateJumpTable(cast
<MachOObjectFile
>(Obj
), Section
, SectionID
);
135 else if (Name
== "__pointers")
136 return populateIndirectSymbolPointersSection(cast
<MachOObjectFile
>(Obj
),
138 return Error::success();
142 Expected
<relocation_iterator
>
143 processSECTDIFFRelocation(unsigned SectionID
, relocation_iterator RelI
,
144 const ObjectFile
&BaseObjT
,
145 ObjSectionToIDMap
&ObjSectionToID
) {
146 const MachOObjectFile
&Obj
=
147 static_cast<const MachOObjectFile
&>(BaseObjT
);
148 MachO::any_relocation_info RE
=
149 Obj
.getRelocation(RelI
->getRawDataRefImpl());
151 SectionEntry
&Section
= Sections
[SectionID
];
152 uint32_t RelocType
= Obj
.getAnyRelocationType(RE
);
153 bool IsPCRel
= Obj
.getAnyRelocationPCRel(RE
);
154 unsigned Size
= Obj
.getAnyRelocationLength(RE
);
155 uint64_t Offset
= RelI
->getOffset();
156 uint8_t *LocalAddress
= Section
.getAddressWithOffset(Offset
);
157 unsigned NumBytes
= 1 << Size
;
158 uint64_t Addend
= readBytesUnaligned(LocalAddress
, NumBytes
);
161 MachO::any_relocation_info RE2
=
162 Obj
.getRelocation(RelI
->getRawDataRefImpl());
164 uint32_t AddrA
= Obj
.getScatteredRelocationValue(RE
);
165 section_iterator SAI
= getSectionByAddress(Obj
, AddrA
);
166 assert(SAI
!= Obj
.section_end() && "Can't find section for address A");
167 uint64_t SectionABase
= SAI
->getAddress();
168 uint64_t SectionAOffset
= AddrA
- SectionABase
;
169 SectionRef SectionA
= *SAI
;
170 bool IsCode
= SectionA
.isText();
171 uint32_t SectionAID
= ~0U;
172 if (auto SectionAIDOrErr
=
173 findOrEmitSection(Obj
, SectionA
, IsCode
, ObjSectionToID
))
174 SectionAID
= *SectionAIDOrErr
;
176 return SectionAIDOrErr
.takeError();
178 uint32_t AddrB
= Obj
.getScatteredRelocationValue(RE2
);
179 section_iterator SBI
= getSectionByAddress(Obj
, AddrB
);
180 assert(SBI
!= Obj
.section_end() && "Can't find section for address B");
181 uint64_t SectionBBase
= SBI
->getAddress();
182 uint64_t SectionBOffset
= AddrB
- SectionBBase
;
183 SectionRef SectionB
= *SBI
;
184 uint32_t SectionBID
= ~0U;
185 if (auto SectionBIDOrErr
=
186 findOrEmitSection(Obj
, SectionB
, IsCode
, ObjSectionToID
))
187 SectionBID
= *SectionBIDOrErr
;
189 return SectionBIDOrErr
.takeError();
191 // Compute the addend 'C' from the original expression 'A - B + C'.
192 Addend
-= AddrA
- AddrB
;
194 LLVM_DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA
195 << ", AddrB: " << AddrB
<< ", Addend: " << Addend
196 << ", SectionA ID: " << SectionAID
<< ", SectionAOffset: "
197 << SectionAOffset
<< ", SectionB ID: " << SectionBID
198 << ", SectionBOffset: " << SectionBOffset
<< "\n");
199 RelocationEntry
R(SectionID
, Offset
, RelocType
, Addend
, SectionAID
,
200 SectionAOffset
, SectionBID
, SectionBOffset
,
203 addRelocationForSection(R
, SectionAID
);
208 // Populate stubs in __jump_table section.
209 Error
populateJumpTable(const MachOObjectFile
&Obj
,
210 const SectionRef
&JTSection
,
211 unsigned JTSectionID
) {
212 MachO::dysymtab_command DySymTabCmd
= Obj
.getDysymtabLoadCommand();
213 MachO::section Sec32
= Obj
.getSection(JTSection
.getRawDataRefImpl());
214 uint32_t JTSectionSize
= Sec32
.size
;
215 unsigned FirstIndirectSymbol
= Sec32
.reserved1
;
216 unsigned JTEntrySize
= Sec32
.reserved2
;
217 unsigned NumJTEntries
= JTSectionSize
/ JTEntrySize
;
218 uint8_t *JTSectionAddr
= getSectionAddress(JTSectionID
);
219 unsigned JTEntryOffset
= 0;
221 if (JTSectionSize
% JTEntrySize
!= 0)
222 return make_error
<RuntimeDyldError
>("Jump-table section does not contain "
223 "a whole number of stubs?");
225 for (unsigned i
= 0; i
< NumJTEntries
; ++i
) {
226 unsigned SymbolIndex
=
227 Obj
.getIndirectSymbolTableEntry(DySymTabCmd
, FirstIndirectSymbol
+ i
);
228 symbol_iterator SI
= Obj
.getSymbolByIndex(SymbolIndex
);
229 Expected
<StringRef
> IndirectSymbolName
= SI
->getName();
230 if (!IndirectSymbolName
)
231 return IndirectSymbolName
.takeError();
232 uint8_t *JTEntryAddr
= JTSectionAddr
+ JTEntryOffset
;
233 createStubFunction(JTEntryAddr
);
234 RelocationEntry
RE(JTSectionID
, JTEntryOffset
+ 1,
235 MachO::GENERIC_RELOC_VANILLA
, 0, true, 2);
236 addRelocationForSymbol(RE
, *IndirectSymbolName
);
237 JTEntryOffset
+= JTEntrySize
;
240 return Error::success();