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