1 //===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- 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 // Implementation of the MC-JIT runtime dynamic linker.
11 //===----------------------------------------------------------------------===//
13 #include "RuntimeDyldMachO.h"
14 #include "Targets/RuntimeDyldMachOAArch64.h"
15 #include "Targets/RuntimeDyldMachOARM.h"
16 #include "Targets/RuntimeDyldMachOI386.h"
17 #include "Targets/RuntimeDyldMachOX86_64.h"
18 #include "llvm/ADT/StringRef.h"
21 using namespace llvm::object
;
23 #define DEBUG_TYPE "dyld"
27 class LoadedMachOObjectInfo final
28 : public LoadedObjectInfoHelper
<LoadedMachOObjectInfo
,
29 RuntimeDyld::LoadedObjectInfo
> {
31 LoadedMachOObjectInfo(RuntimeDyldImpl
&RTDyld
,
32 ObjSectionToIDMap ObjSecToIDMap
)
33 : LoadedObjectInfoHelper(RTDyld
, std::move(ObjSecToIDMap
)) {}
35 OwningBinary
<ObjectFile
>
36 getObjectForDebug(const ObjectFile
&Obj
) const override
{
37 return OwningBinary
<ObjectFile
>();
45 int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry
&RE
) const {
46 unsigned NumBytes
= 1 << RE
.Size
;
47 uint8_t *Src
= Sections
[RE
.SectionID
].getAddress() + RE
.Offset
;
49 return static_cast<int64_t>(readBytesUnaligned(Src
, NumBytes
));
52 Expected
<relocation_iterator
>
53 RuntimeDyldMachO::processScatteredVANILLA(
54 unsigned SectionID
, relocation_iterator RelI
,
55 const ObjectFile
&BaseObjT
,
56 RuntimeDyldMachO::ObjSectionToIDMap
&ObjSectionToID
,
57 bool TargetIsLocalThumbFunc
) {
58 const MachOObjectFile
&Obj
=
59 static_cast<const MachOObjectFile
&>(BaseObjT
);
60 MachO::any_relocation_info RE
=
61 Obj
.getRelocation(RelI
->getRawDataRefImpl());
63 SectionEntry
&Section
= Sections
[SectionID
];
64 uint32_t RelocType
= Obj
.getAnyRelocationType(RE
);
65 bool IsPCRel
= Obj
.getAnyRelocationPCRel(RE
);
66 unsigned Size
= Obj
.getAnyRelocationLength(RE
);
67 uint64_t Offset
= RelI
->getOffset();
68 uint8_t *LocalAddress
= Section
.getAddressWithOffset(Offset
);
69 unsigned NumBytes
= 1 << Size
;
70 int64_t Addend
= readBytesUnaligned(LocalAddress
, NumBytes
);
72 unsigned SymbolBaseAddr
= Obj
.getScatteredRelocationValue(RE
);
73 section_iterator TargetSI
= getSectionByAddress(Obj
, SymbolBaseAddr
);
74 assert(TargetSI
!= Obj
.section_end() && "Can't find section for symbol");
75 uint64_t SectionBaseAddr
= TargetSI
->getAddress();
76 SectionRef TargetSection
= *TargetSI
;
77 bool IsCode
= TargetSection
.isText();
78 uint32_t TargetSectionID
= ~0U;
79 if (auto TargetSectionIDOrErr
=
80 findOrEmitSection(Obj
, TargetSection
, IsCode
, ObjSectionToID
))
81 TargetSectionID
= *TargetSectionIDOrErr
;
83 return TargetSectionIDOrErr
.takeError();
85 Addend
-= SectionBaseAddr
;
86 RelocationEntry
R(SectionID
, Offset
, RelocType
, Addend
, IsPCRel
, Size
);
87 R
.IsTargetThumbFunc
= TargetIsLocalThumbFunc
;
89 addRelocationForSection(R
, TargetSectionID
);
95 Expected
<RelocationValueRef
>
96 RuntimeDyldMachO::getRelocationValueRef(
97 const ObjectFile
&BaseTObj
, const relocation_iterator
&RI
,
98 const RelocationEntry
&RE
, ObjSectionToIDMap
&ObjSectionToID
) {
100 const MachOObjectFile
&Obj
=
101 static_cast<const MachOObjectFile
&>(BaseTObj
);
102 MachO::any_relocation_info RelInfo
=
103 Obj
.getRelocation(RI
->getRawDataRefImpl());
104 RelocationValueRef Value
;
106 bool IsExternal
= Obj
.getPlainRelocationExternal(RelInfo
);
108 symbol_iterator Symbol
= RI
->getSymbol();
109 StringRef TargetName
;
110 if (auto TargetNameOrErr
= Symbol
->getName())
111 TargetName
= *TargetNameOrErr
;
113 return TargetNameOrErr
.takeError();
114 RTDyldSymbolTable::const_iterator SI
=
115 GlobalSymbolTable
.find(TargetName
.data());
116 if (SI
!= GlobalSymbolTable
.end()) {
117 const auto &SymInfo
= SI
->second
;
118 Value
.SectionID
= SymInfo
.getSectionID();
119 Value
.Offset
= SymInfo
.getOffset() + RE
.Addend
;
121 Value
.SymbolName
= TargetName
.data();
122 Value
.Offset
= RE
.Addend
;
125 SectionRef Sec
= Obj
.getAnyRelocationSection(RelInfo
);
126 bool IsCode
= Sec
.isText();
127 if (auto SectionIDOrErr
= findOrEmitSection(Obj
, Sec
, IsCode
,
129 Value
.SectionID
= *SectionIDOrErr
;
131 return SectionIDOrErr
.takeError();
132 uint64_t Addr
= Sec
.getAddress();
133 Value
.Offset
= RE
.Addend
- Addr
;
139 void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef
&Value
,
140 const relocation_iterator
&RI
,
141 unsigned OffsetToNextPC
) {
142 auto &O
= *cast
<MachOObjectFile
>(RI
->getObject());
143 section_iterator SecI
= O
.getRelocationRelocatedSection(RI
);
144 Value
.Offset
+= RI
->getOffset() + OffsetToNextPC
+ SecI
->getAddress();
147 void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry
&RE
,
148 uint64_t Value
) const {
149 const SectionEntry
&Section
= Sections
[RE
.SectionID
];
150 uint8_t *LocalAddress
= Section
.getAddress() + RE
.Offset
;
151 uint64_t FinalAddress
= Section
.getLoadAddress() + RE
.Offset
;
153 dbgs() << "resolveRelocation Section: " << RE
.SectionID
154 << " LocalAddress: " << format("%p", LocalAddress
)
155 << " FinalAddress: " << format("0x%016" PRIx64
, FinalAddress
)
156 << " Value: " << format("0x%016" PRIx64
, Value
) << " Addend: " << RE
.Addend
157 << " isPCRel: " << RE
.IsPCRel
<< " MachoType: " << RE
.RelType
158 << " Size: " << (1 << RE
.Size
) << "\n";
162 RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile
&Obj
,
164 section_iterator SI
= Obj
.section_begin();
165 section_iterator SE
= Obj
.section_end();
167 for (; SI
!= SE
; ++SI
) {
168 uint64_t SAddr
= SI
->getAddress();
169 uint64_t SSize
= SI
->getSize();
170 if ((Addr
>= SAddr
) && (Addr
< SAddr
+ SSize
))
178 // Populate __pointers section.
179 Error
RuntimeDyldMachO::populateIndirectSymbolPointersSection(
180 const MachOObjectFile
&Obj
,
181 const SectionRef
&PTSection
,
182 unsigned PTSectionID
) {
183 assert(!Obj
.is64Bit() &&
184 "Pointer table section not supported in 64-bit MachO.");
186 MachO::dysymtab_command DySymTabCmd
= Obj
.getDysymtabLoadCommand();
187 MachO::section Sec32
= Obj
.getSection(PTSection
.getRawDataRefImpl());
188 uint32_t PTSectionSize
= Sec32
.size
;
189 unsigned FirstIndirectSymbol
= Sec32
.reserved1
;
190 const unsigned PTEntrySize
= 4;
191 unsigned NumPTEntries
= PTSectionSize
/ PTEntrySize
;
192 unsigned PTEntryOffset
= 0;
194 assert((PTSectionSize
% PTEntrySize
) == 0 &&
195 "Pointers section does not contain a whole number of stubs?");
197 LLVM_DEBUG(dbgs() << "Populating pointer table section "
198 << Sections
[PTSectionID
].getName() << ", Section ID "
199 << PTSectionID
<< ", " << NumPTEntries
<< " entries, "
200 << PTEntrySize
<< " bytes each:\n");
202 for (unsigned i
= 0; i
< NumPTEntries
; ++i
) {
203 unsigned SymbolIndex
=
204 Obj
.getIndirectSymbolTableEntry(DySymTabCmd
, FirstIndirectSymbol
+ i
);
205 symbol_iterator SI
= Obj
.getSymbolByIndex(SymbolIndex
);
206 StringRef IndirectSymbolName
;
207 if (auto IndirectSymbolNameOrErr
= SI
->getName())
208 IndirectSymbolName
= *IndirectSymbolNameOrErr
;
210 return IndirectSymbolNameOrErr
.takeError();
211 LLVM_DEBUG(dbgs() << " " << IndirectSymbolName
<< ": index " << SymbolIndex
212 << ", PT offset: " << PTEntryOffset
<< "\n");
213 RelocationEntry
RE(PTSectionID
, PTEntryOffset
,
214 MachO::GENERIC_RELOC_VANILLA
, 0, false, 2);
215 addRelocationForSymbol(RE
, IndirectSymbolName
);
216 PTEntryOffset
+= PTEntrySize
;
218 return Error::success();
221 bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile
&Obj
) const {
222 return Obj
.isMachO();
225 template <typename Impl
>
227 RuntimeDyldMachOCRTPBase
<Impl
>::finalizeLoad(const ObjectFile
&Obj
,
228 ObjSectionToIDMap
&SectionMap
) {
229 unsigned EHFrameSID
= RTDYLD_INVALID_SECTION_ID
;
230 unsigned TextSID
= RTDYLD_INVALID_SECTION_ID
;
231 unsigned ExceptTabSID
= RTDYLD_INVALID_SECTION_ID
;
233 for (const auto &Section
: Obj
.sections()) {
235 if (Expected
<StringRef
> NameOrErr
= Section
.getName())
238 consumeError(NameOrErr
.takeError());
240 // Force emission of the __text, __eh_frame, and __gcc_except_tab sections
241 // if they're present. Otherwise call down to the impl to handle other
242 // sections that have already been emitted.
243 if (Name
== "__text") {
244 if (auto TextSIDOrErr
= findOrEmitSection(Obj
, Section
, true, SectionMap
))
245 TextSID
= *TextSIDOrErr
;
247 return TextSIDOrErr
.takeError();
248 } else if (Name
== "__eh_frame") {
249 if (auto EHFrameSIDOrErr
= findOrEmitSection(Obj
, Section
, false,
251 EHFrameSID
= *EHFrameSIDOrErr
;
253 return EHFrameSIDOrErr
.takeError();
254 } else if (Name
== "__gcc_except_tab") {
255 if (auto ExceptTabSIDOrErr
= findOrEmitSection(Obj
, Section
, true,
257 ExceptTabSID
= *ExceptTabSIDOrErr
;
259 return ExceptTabSIDOrErr
.takeError();
261 auto I
= SectionMap
.find(Section
);
262 if (I
!= SectionMap
.end())
263 if (auto Err
= impl().finalizeSection(Obj
, I
->second
, Section
))
267 UnregisteredEHFrameSections
.push_back(
268 EHFrameRelatedSections(EHFrameSID
, TextSID
, ExceptTabSID
));
270 return Error::success();
273 template <typename Impl
>
274 unsigned char *RuntimeDyldMachOCRTPBase
<Impl
>::processFDE(uint8_t *P
,
275 int64_t DeltaForText
,
276 int64_t DeltaForEH
) {
277 typedef typename
Impl::TargetPtrT TargetPtrT
;
279 LLVM_DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText
280 << ", Delta for EH: " << DeltaForEH
<< "\n");
281 uint32_t Length
= readBytesUnaligned(P
, 4);
283 uint8_t *Ret
= P
+ Length
;
284 uint32_t Offset
= readBytesUnaligned(P
, 4);
285 if (Offset
== 0) // is a CIE
289 TargetPtrT FDELocation
= readBytesUnaligned(P
, sizeof(TargetPtrT
));
290 TargetPtrT NewLocation
= FDELocation
- DeltaForText
;
291 writeBytesUnaligned(NewLocation
, P
, sizeof(TargetPtrT
));
293 P
+= sizeof(TargetPtrT
);
295 // Skip the FDE address range
296 P
+= sizeof(TargetPtrT
);
298 uint8_t Augmentationsize
= *P
;
300 if (Augmentationsize
!= 0) {
301 TargetPtrT LSDA
= readBytesUnaligned(P
, sizeof(TargetPtrT
));
302 TargetPtrT NewLSDA
= LSDA
- DeltaForEH
;
303 writeBytesUnaligned(NewLSDA
, P
, sizeof(TargetPtrT
));
309 static int64_t computeDelta(SectionEntry
*A
, SectionEntry
*B
) {
310 int64_t ObjDistance
= static_cast<int64_t>(A
->getObjAddress()) -
311 static_cast<int64_t>(B
->getObjAddress());
312 int64_t MemDistance
= A
->getLoadAddress() - B
->getLoadAddress();
313 return ObjDistance
- MemDistance
;
316 template <typename Impl
>
317 void RuntimeDyldMachOCRTPBase
<Impl
>::registerEHFrames() {
319 for (int i
= 0, e
= UnregisteredEHFrameSections
.size(); i
!= e
; ++i
) {
320 EHFrameRelatedSections
&SectionInfo
= UnregisteredEHFrameSections
[i
];
321 if (SectionInfo
.EHFrameSID
== RTDYLD_INVALID_SECTION_ID
||
322 SectionInfo
.TextSID
== RTDYLD_INVALID_SECTION_ID
)
324 SectionEntry
*Text
= &Sections
[SectionInfo
.TextSID
];
325 SectionEntry
*EHFrame
= &Sections
[SectionInfo
.EHFrameSID
];
326 SectionEntry
*ExceptTab
= nullptr;
327 if (SectionInfo
.ExceptTabSID
!= RTDYLD_INVALID_SECTION_ID
)
328 ExceptTab
= &Sections
[SectionInfo
.ExceptTabSID
];
330 int64_t DeltaForText
= computeDelta(Text
, EHFrame
);
331 int64_t DeltaForEH
= 0;
333 DeltaForEH
= computeDelta(ExceptTab
, EHFrame
);
335 uint8_t *P
= EHFrame
->getAddress();
336 uint8_t *End
= P
+ EHFrame
->getSize();
338 P
= processFDE(P
, DeltaForText
, DeltaForEH
);
341 MemMgr
.registerEHFrames(EHFrame
->getAddress(), EHFrame
->getLoadAddress(),
344 UnregisteredEHFrameSections
.clear();
347 std::unique_ptr
<RuntimeDyldMachO
>
348 RuntimeDyldMachO::create(Triple::ArchType Arch
,
349 RuntimeDyld::MemoryManager
&MemMgr
,
350 JITSymbolResolver
&Resolver
) {
353 llvm_unreachable("Unsupported target for RuntimeDyldMachO.");
356 return std::make_unique
<RuntimeDyldMachOARM
>(MemMgr
, Resolver
);
357 case Triple::aarch64
:
358 return std::make_unique
<RuntimeDyldMachOAArch64
>(MemMgr
, Resolver
);
359 case Triple::aarch64_32
:
360 return std::make_unique
<RuntimeDyldMachOAArch64
>(MemMgr
, Resolver
);
362 return std::make_unique
<RuntimeDyldMachOI386
>(MemMgr
, Resolver
);
364 return std::make_unique
<RuntimeDyldMachOX86_64
>(MemMgr
, Resolver
);
368 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
>
369 RuntimeDyldMachO::loadObject(const object::ObjectFile
&O
) {
370 if (auto ObjSectionToIDOrErr
= loadObjectImpl(O
))
371 return std::make_unique
<LoadedMachOObjectInfo
>(*this,
372 *ObjSectionToIDOrErr
);
375 raw_string_ostream
ErrStream(ErrorStr
);
376 logAllUnhandledErrors(ObjSectionToIDOrErr
.takeError(), ErrStream
);
381 } // end namespace llvm