1 //===-- RuntimeDyldMachOX86_64.h ---- MachO/X86_64 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_RUNTIMEDYLDMACHOX86_64_H
10 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOX86_64_H
12 #include "../RuntimeDyldMachO.h"
15 #define DEBUG_TYPE "dyld"
19 class RuntimeDyldMachOX86_64
20 : public RuntimeDyldMachOCRTPBase
<RuntimeDyldMachOX86_64
> {
23 typedef uint64_t TargetPtrT
;
25 RuntimeDyldMachOX86_64(RuntimeDyld::MemoryManager
&MM
,
26 JITSymbolResolver
&Resolver
)
27 : RuntimeDyldMachOCRTPBase(MM
, Resolver
) {}
29 unsigned getMaxStubSize() const override
{ return 8; }
31 unsigned getStubAlignment() override
{ return 8; }
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 (RelType
== MachO::X86_64_RELOC_SUBTRACTOR
)
45 return processSubtractRelocation(SectionID
, RelI
, Obj
, ObjSectionToID
);
47 assert(!Obj
.isRelocationScattered(RelInfo
) &&
48 "Scattered relocations not supported on X86_64");
50 RelocationEntry
RE(getRelocationEntry(SectionID
, Obj
, RelI
));
51 RE
.Addend
= memcpyAddend(RE
);
52 RelocationValueRef Value
;
53 if (auto ValueOrErr
= getRelocationValueRef(Obj
, RelI
, RE
, ObjSectionToID
))
56 return ValueOrErr
.takeError();
58 bool IsExtern
= Obj
.getPlainRelocationExternal(RelInfo
);
59 if (!IsExtern
&& RE
.IsPCRel
)
60 makeValueAddendPCRel(Value
, RelI
, 1 << RE
.Size
);
63 UNIMPLEMENTED_RELOC(MachO::X86_64_RELOC_TLV
);
65 if (RelType
> MachO::X86_64_RELOC_TLV
)
66 return make_error
<RuntimeDyldError
>(("MachO X86_64 relocation type " +
68 " is out of range").str());
72 if (RE
.RelType
== MachO::X86_64_RELOC_GOT
||
73 RE
.RelType
== MachO::X86_64_RELOC_GOT_LOAD
)
74 processGOTRelocation(RE
, Value
, Stubs
);
76 RE
.Addend
= Value
.Offset
;
78 addRelocationForSymbol(RE
, Value
.SymbolName
);
80 addRelocationForSection(RE
, Value
.SectionID
);
86 void resolveRelocation(const RelocationEntry
&RE
, uint64_t Value
) override
{
87 LLVM_DEBUG(dumpRelocationToResolve(RE
, Value
));
88 const SectionEntry
&Section
= Sections
[RE
.SectionID
];
89 uint8_t *LocalAddress
= Section
.getAddressWithOffset(RE
.Offset
);
91 // If the relocation is PC-relative, the value to be encoded is the
92 // pointer difference.
94 // FIXME: It seems this value needs to be adjusted by 4 for an effective
95 // PC address. Is that expected? Only for branches, perhaps?
96 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(RE
.Offset
);
97 Value
-= FinalAddress
+ 4;
100 switch (RE
.RelType
) {
102 llvm_unreachable("Invalid relocation type!");
103 case MachO::X86_64_RELOC_SIGNED_1
:
104 case MachO::X86_64_RELOC_SIGNED_2
:
105 case MachO::X86_64_RELOC_SIGNED_4
:
106 case MachO::X86_64_RELOC_SIGNED
:
107 case MachO::X86_64_RELOC_UNSIGNED
:
108 case MachO::X86_64_RELOC_BRANCH
:
109 writeBytesUnaligned(Value
+ RE
.Addend
, LocalAddress
, 1 << RE
.Size
);
111 case MachO::X86_64_RELOC_SUBTRACTOR
: {
112 uint64_t SectionABase
= Sections
[RE
.Sections
.SectionA
].getLoadAddress();
113 uint64_t SectionBBase
= Sections
[RE
.Sections
.SectionB
].getLoadAddress();
114 assert((Value
== SectionABase
|| Value
== SectionBBase
) &&
115 "Unexpected SUBTRACTOR relocation value.");
116 Value
= SectionABase
- SectionBBase
+ RE
.Addend
;
117 writeBytesUnaligned(Value
, LocalAddress
, 1 << RE
.Size
);
123 Error
finalizeSection(const ObjectFile
&Obj
, unsigned SectionID
,
124 const SectionRef
&Section
) {
125 return Error::success();
129 void processGOTRelocation(const RelocationEntry
&RE
,
130 RelocationValueRef
&Value
, StubMap
&Stubs
) {
131 SectionEntry
&Section
= Sections
[RE
.SectionID
];
133 assert(RE
.Size
== 2);
134 Value
.Offset
-= RE
.Addend
;
135 RuntimeDyldMachO::StubMap::const_iterator i
= Stubs
.find(Value
);
137 if (i
!= Stubs
.end()) {
138 Addr
= Section
.getAddressWithOffset(i
->second
);
140 Stubs
[Value
] = Section
.getStubOffset();
141 uint8_t *GOTEntry
= Section
.getAddressWithOffset(Section
.getStubOffset());
142 RelocationEntry
GOTRE(RE
.SectionID
, Section
.getStubOffset(),
143 MachO::X86_64_RELOC_UNSIGNED
, Value
.Offset
, false,
145 if (Value
.SymbolName
)
146 addRelocationForSymbol(GOTRE
, Value
.SymbolName
);
148 addRelocationForSection(GOTRE
, Value
.SectionID
);
149 Section
.advanceStubOffset(8);
152 RelocationEntry
TargetRE(RE
.SectionID
, RE
.Offset
,
153 MachO::X86_64_RELOC_UNSIGNED
, RE
.Addend
, true, 2);
154 resolveRelocation(TargetRE
, (uint64_t)Addr
);
157 Expected
<relocation_iterator
>
158 processSubtractRelocation(unsigned SectionID
, relocation_iterator RelI
,
159 const MachOObjectFile
&BaseObj
,
160 ObjSectionToIDMap
&ObjSectionToID
) {
161 const MachOObjectFile
&Obj
=
162 static_cast<const MachOObjectFile
&>(BaseObj
);
163 MachO::any_relocation_info RE
=
164 Obj
.getRelocation(RelI
->getRawDataRefImpl());
166 unsigned Size
= Obj
.getAnyRelocationLength(RE
);
167 uint64_t Offset
= RelI
->getOffset();
168 uint8_t *LocalAddress
= Sections
[SectionID
].getAddressWithOffset(Offset
);
169 unsigned NumBytes
= 1 << Size
;
171 SignExtend64(readBytesUnaligned(LocalAddress
, NumBytes
), NumBytes
* 8);
173 unsigned SectionBID
= ~0U;
174 uint64_t SectionBOffset
= 0;
176 MachO::any_relocation_info RelInfo
=
177 Obj
.getRelocation(RelI
->getRawDataRefImpl());
179 bool AIsExternal
= BaseObj
.getPlainRelocationExternal(RelInfo
);
182 Expected
<StringRef
> SubtrahendNameOrErr
= RelI
->getSymbol()->getName();
183 if (!SubtrahendNameOrErr
)
184 return SubtrahendNameOrErr
.takeError();
185 auto SubtrahendI
= GlobalSymbolTable
.find(*SubtrahendNameOrErr
);
186 SectionBID
= SubtrahendI
->second
.getSectionID();
187 SectionBOffset
= SubtrahendI
->second
.getOffset();
189 SectionRef SecB
= Obj
.getAnyRelocationSection(RelInfo
);
190 bool IsCode
= SecB
.isText();
191 Expected
<unsigned> SectionBIDOrErr
=
192 findOrEmitSection(Obj
, SecB
, IsCode
, ObjSectionToID
);
193 if (!SectionBIDOrErr
)
194 return SectionBIDOrErr
.takeError();
195 SectionBID
= *SectionBIDOrErr
;
196 Addend
+= SecB
.getAddress();
201 unsigned SectionAID
= ~0U;
202 uint64_t SectionAOffset
= 0;
204 RelInfo
= Obj
.getRelocation(RelI
->getRawDataRefImpl());
206 bool BIsExternal
= BaseObj
.getPlainRelocationExternal(RelInfo
);
208 Expected
<StringRef
> MinuendNameOrErr
= RelI
->getSymbol()->getName();
209 if (!MinuendNameOrErr
)
210 return MinuendNameOrErr
.takeError();
211 auto MinuendI
= GlobalSymbolTable
.find(*MinuendNameOrErr
);
212 SectionAID
= MinuendI
->second
.getSectionID();
213 SectionAOffset
= MinuendI
->second
.getOffset();
215 SectionRef SecA
= Obj
.getAnyRelocationSection(RelInfo
);
216 bool IsCode
= SecA
.isText();
217 Expected
<unsigned> SectionAIDOrErr
=
218 findOrEmitSection(Obj
, SecA
, IsCode
, ObjSectionToID
);
219 if (!SectionAIDOrErr
)
220 return SectionAIDOrErr
.takeError();
221 SectionAID
= *SectionAIDOrErr
;
222 Addend
-= SecA
.getAddress();
225 RelocationEntry
R(SectionID
, Offset
, MachO::X86_64_RELOC_SUBTRACTOR
, (uint64_t)Addend
,
226 SectionAID
, SectionAOffset
, SectionBID
, SectionBOffset
,
229 addRelocationForSection(R
, SectionAID
);