1 //===--- RuntimeDyldCOFFI386.h --- COFF/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 // COFF x86 support for MC-JIT runtime dynamic linker.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
14 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
16 #include "../RuntimeDyldCOFF.h"
17 #include "llvm/BinaryFormat/COFF.h"
18 #include "llvm/Object/COFF.h"
20 #define DEBUG_TYPE "dyld"
24 class RuntimeDyldCOFFI386
: public RuntimeDyldCOFF
{
26 RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager
&MM
,
27 JITSymbolResolver
&Resolver
)
28 : RuntimeDyldCOFF(MM
, Resolver
, 4, COFF::IMAGE_REL_I386_DIR32
) {}
30 unsigned getMaxStubSize() const override
{
31 return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
34 Align
getStubAlignment() override
{ return Align(1); }
36 Expected
<object::relocation_iterator
>
37 processRelocationRef(unsigned SectionID
,
38 object::relocation_iterator RelI
,
39 const object::ObjectFile
&Obj
,
40 ObjSectionToIDMap
&ObjSectionToID
,
41 StubMap
&Stubs
) override
{
43 auto Symbol
= RelI
->getSymbol();
44 if (Symbol
== Obj
.symbol_end())
45 report_fatal_error("Unknown symbol in relocation");
47 Expected
<StringRef
> TargetNameOrErr
= Symbol
->getName();
49 return TargetNameOrErr
.takeError();
50 StringRef TargetName
= *TargetNameOrErr
;
52 auto SectionOrErr
= Symbol
->getSection();
54 return SectionOrErr
.takeError();
55 auto Section
= *SectionOrErr
;
56 bool IsExtern
= Section
== Obj
.section_end();
58 uint64_t RelType
= RelI
->getType();
59 uint64_t Offset
= RelI
->getOffset();
61 unsigned TargetSectionID
= -1;
62 uint64_t TargetOffset
= -1;
63 if (TargetName
.startswith(getImportSymbolPrefix())) {
64 TargetSectionID
= SectionID
;
65 TargetOffset
= getDLLImportOffset(SectionID
, Stubs
, TargetName
, true);
66 TargetName
= StringRef();
68 } else if (!IsExtern
) {
69 if (auto TargetSectionIDOrErr
= findOrEmitSection(
70 Obj
, *Section
, Section
->isText(), ObjSectionToID
))
71 TargetSectionID
= *TargetSectionIDOrErr
;
73 return TargetSectionIDOrErr
.takeError();
74 if (RelType
!= COFF::IMAGE_REL_I386_SECTION
)
75 TargetOffset
= getSymbolOffset(*Symbol
);
78 // Determine the Addend used to adjust the relocation value.
80 SectionEntry
&AddendSection
= Sections
[SectionID
];
81 uintptr_t ObjTarget
= AddendSection
.getObjAddress() + Offset
;
82 uint8_t *Displacement
= (uint8_t *)ObjTarget
;
85 case COFF::IMAGE_REL_I386_DIR32
:
86 case COFF::IMAGE_REL_I386_DIR32NB
:
87 case COFF::IMAGE_REL_I386_SECREL
:
88 case COFF::IMAGE_REL_I386_REL32
: {
89 Addend
= readBytesUnaligned(Displacement
, 4);
97 SmallString
<32> RelTypeName
;
98 RelI
->getTypeName(RelTypeName
);
100 LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID
<< " Offset " << Offset
101 << " RelType: " << RelTypeName
<< " TargetName: "
102 << TargetName
<< " Addend " << Addend
<< "\n");
105 RelocationEntry
RE(SectionID
, Offset
, RelType
, 0, -1, 0, 0, 0, false, 0);
106 addRelocationForSymbol(RE
, TargetName
);
110 case COFF::IMAGE_REL_I386_ABSOLUTE
:
111 // This relocation is ignored.
113 case COFF::IMAGE_REL_I386_DIR32
:
114 case COFF::IMAGE_REL_I386_DIR32NB
:
115 case COFF::IMAGE_REL_I386_REL32
: {
117 RelocationEntry(SectionID
, Offset
, RelType
, Addend
, TargetSectionID
,
118 TargetOffset
, 0, 0, false, 0);
119 addRelocationForSection(RE
, TargetSectionID
);
122 case COFF::IMAGE_REL_I386_SECTION
: {
124 RelocationEntry(TargetSectionID
, Offset
, RelType
, 0);
125 addRelocationForSection(RE
, TargetSectionID
);
128 case COFF::IMAGE_REL_I386_SECREL
: {
130 RelocationEntry(SectionID
, Offset
, RelType
, TargetOffset
+ Addend
);
131 addRelocationForSection(RE
, TargetSectionID
);
135 llvm_unreachable("unsupported relocation type");
142 void resolveRelocation(const RelocationEntry
&RE
, uint64_t Value
) override
{
143 const auto Section
= Sections
[RE
.SectionID
];
144 uint8_t *Target
= Section
.getAddressWithOffset(RE
.Offset
);
146 switch (RE
.RelType
) {
147 case COFF::IMAGE_REL_I386_ABSOLUTE
:
148 // This relocation is ignored.
150 case COFF::IMAGE_REL_I386_DIR32
: {
151 // The target's 32-bit VA.
153 RE
.Sections
.SectionA
== static_cast<uint32_t>(-1)
155 : Sections
[RE
.Sections
.SectionA
].getLoadAddressWithOffset(
157 assert(Result
<= UINT32_MAX
&& "relocation overflow");
158 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE
.Offset
159 << " RelType: IMAGE_REL_I386_DIR32"
160 << " TargetSection: " << RE
.Sections
.SectionA
161 << " Value: " << format("0x%08" PRIx32
, Result
)
163 writeBytesUnaligned(Result
, Target
, 4);
166 case COFF::IMAGE_REL_I386_DIR32NB
: {
167 // The target's 32-bit RVA.
168 // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
170 Sections
[RE
.Sections
.SectionA
].getLoadAddressWithOffset(RE
.Addend
) -
171 Sections
[0].getLoadAddress();
172 assert(Result
<= UINT32_MAX
&& "relocation overflow");
173 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE
.Offset
174 << " RelType: IMAGE_REL_I386_DIR32NB"
175 << " TargetSection: " << RE
.Sections
.SectionA
176 << " Value: " << format("0x%08" PRIx32
, Result
)
178 writeBytesUnaligned(Result
, Target
, 4);
181 case COFF::IMAGE_REL_I386_REL32
: {
182 // 32-bit relative displacement to the target.
183 uint64_t Result
= RE
.Sections
.SectionA
== static_cast<uint32_t>(-1)
185 : Sections
[RE
.Sections
.SectionA
].getLoadAddress();
186 Result
= Result
- Section
.getLoadAddress() + RE
.Addend
- 4 - RE
.Offset
;
187 assert(static_cast<int64_t>(Result
) <= INT32_MAX
&&
188 "relocation overflow");
189 assert(static_cast<int64_t>(Result
) >= INT32_MIN
&&
190 "relocation underflow");
191 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE
.Offset
192 << " RelType: IMAGE_REL_I386_REL32"
193 << " TargetSection: " << RE
.Sections
.SectionA
194 << " Value: " << format("0x%08" PRIx32
, Result
)
196 writeBytesUnaligned(Result
, Target
, 4);
199 case COFF::IMAGE_REL_I386_SECTION
:
200 // 16-bit section index of the section that contains the target.
201 assert(static_cast<uint32_t>(RE
.SectionID
) <= UINT16_MAX
&&
202 "relocation overflow");
203 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE
.Offset
204 << " RelType: IMAGE_REL_I386_SECTION Value: "
205 << RE
.SectionID
<< '\n');
206 writeBytesUnaligned(RE
.SectionID
, Target
, 2);
208 case COFF::IMAGE_REL_I386_SECREL
:
209 // 32-bit offset of the target from the beginning of its section.
210 assert(static_cast<uint64_t>(RE
.Addend
) <= UINT32_MAX
&&
211 "relocation overflow");
212 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE
.Offset
213 << " RelType: IMAGE_REL_I386_SECREL Value: "
214 << RE
.Addend
<< '\n');
215 writeBytesUnaligned(RE
.Addend
, Target
, 4);
218 llvm_unreachable("unsupported relocation type");
222 void registerEHFrames() override
{}