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
) {}
30 unsigned getMaxStubSize() const override
{
31 return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
34 unsigned getStubAlignment() override
{ return 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
;
57 uint64_t RelType
= RelI
->getType();
58 uint64_t Offset
= RelI
->getOffset();
60 // Determine the Addend used to adjust the relocation value.
62 SectionEntry
&AddendSection
= Sections
[SectionID
];
63 uintptr_t ObjTarget
= AddendSection
.getObjAddress() + Offset
;
64 uint8_t *Displacement
= (uint8_t *)ObjTarget
;
67 case COFF::IMAGE_REL_I386_DIR32
:
68 case COFF::IMAGE_REL_I386_DIR32NB
:
69 case COFF::IMAGE_REL_I386_SECREL
:
70 case COFF::IMAGE_REL_I386_REL32
: {
71 Addend
= readBytesUnaligned(Displacement
, 4);
79 SmallString
<32> RelTypeName
;
80 RelI
->getTypeName(RelTypeName
);
82 LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID
<< " Offset " << Offset
83 << " RelType: " << RelTypeName
<< " TargetName: "
84 << TargetName
<< " Addend " << Addend
<< "\n");
86 unsigned TargetSectionID
= -1;
87 if (Section
== Obj
.section_end()) {
88 RelocationEntry
RE(SectionID
, Offset
, RelType
, 0, -1, 0, 0, 0, false, 0);
89 addRelocationForSymbol(RE
, TargetName
);
91 if (auto TargetSectionIDOrErr
=
92 findOrEmitSection(Obj
, *Section
, Section
->isText(), ObjSectionToID
))
93 TargetSectionID
= *TargetSectionIDOrErr
;
95 return TargetSectionIDOrErr
.takeError();
98 case COFF::IMAGE_REL_I386_ABSOLUTE
:
99 // This relocation is ignored.
101 case COFF::IMAGE_REL_I386_DIR32
:
102 case COFF::IMAGE_REL_I386_DIR32NB
:
103 case COFF::IMAGE_REL_I386_REL32
: {
105 RelocationEntry(SectionID
, Offset
, RelType
, Addend
, TargetSectionID
,
106 getSymbolOffset(*Symbol
), 0, 0, false, 0);
107 addRelocationForSection(RE
, TargetSectionID
);
110 case COFF::IMAGE_REL_I386_SECTION
: {
112 RelocationEntry(TargetSectionID
, Offset
, RelType
, 0);
113 addRelocationForSection(RE
, TargetSectionID
);
116 case COFF::IMAGE_REL_I386_SECREL
: {
117 RelocationEntry RE
= RelocationEntry(SectionID
, Offset
, RelType
,
118 getSymbolOffset(*Symbol
) + Addend
);
119 addRelocationForSection(RE
, TargetSectionID
);
123 llvm_unreachable("unsupported relocation type");
131 void resolveRelocation(const RelocationEntry
&RE
, uint64_t Value
) override
{
132 const auto Section
= Sections
[RE
.SectionID
];
133 uint8_t *Target
= Section
.getAddressWithOffset(RE
.Offset
);
135 switch (RE
.RelType
) {
136 case COFF::IMAGE_REL_I386_ABSOLUTE
:
137 // This relocation is ignored.
139 case COFF::IMAGE_REL_I386_DIR32
: {
140 // The target's 32-bit VA.
142 RE
.Sections
.SectionA
== static_cast<uint32_t>(-1)
144 : Sections
[RE
.Sections
.SectionA
].getLoadAddressWithOffset(
146 assert(Result
<= UINT32_MAX
&& "relocation overflow");
147 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE
.Offset
148 << " RelType: IMAGE_REL_I386_DIR32"
149 << " TargetSection: " << RE
.Sections
.SectionA
150 << " Value: " << format("0x%08" PRIx32
, Result
)
152 writeBytesUnaligned(Result
, Target
, 4);
155 case COFF::IMAGE_REL_I386_DIR32NB
: {
156 // The target's 32-bit RVA.
157 // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
159 Sections
[RE
.Sections
.SectionA
].getLoadAddressWithOffset(RE
.Addend
) -
160 Sections
[0].getLoadAddress();
161 assert(Result
<= UINT32_MAX
&& "relocation overflow");
162 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE
.Offset
163 << " RelType: IMAGE_REL_I386_DIR32NB"
164 << " TargetSection: " << RE
.Sections
.SectionA
165 << " Value: " << format("0x%08" PRIx32
, Result
)
167 writeBytesUnaligned(Result
, Target
, 4);
170 case COFF::IMAGE_REL_I386_REL32
: {
171 // 32-bit relative displacement to the target.
172 uint64_t Result
= RE
.Sections
.SectionA
== static_cast<uint32_t>(-1)
174 : Sections
[RE
.Sections
.SectionA
].getLoadAddress();
175 Result
= Result
- Section
.getLoadAddress() + RE
.Addend
- 4 - RE
.Offset
;
176 assert(static_cast<int64_t>(Result
) <= INT32_MAX
&&
177 "relocation overflow");
178 assert(static_cast<int64_t>(Result
) >= INT32_MIN
&&
179 "relocation underflow");
180 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE
.Offset
181 << " RelType: IMAGE_REL_I386_REL32"
182 << " TargetSection: " << RE
.Sections
.SectionA
183 << " Value: " << format("0x%08" PRIx32
, Result
)
185 writeBytesUnaligned(Result
, Target
, 4);
188 case COFF::IMAGE_REL_I386_SECTION
:
189 // 16-bit section index of the section that contains the target.
190 assert(static_cast<uint32_t>(RE
.SectionID
) <= UINT16_MAX
&&
191 "relocation overflow");
192 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE
.Offset
193 << " RelType: IMAGE_REL_I386_SECTION Value: "
194 << RE
.SectionID
<< '\n');
195 writeBytesUnaligned(RE
.SectionID
, Target
, 2);
197 case COFF::IMAGE_REL_I386_SECREL
:
198 // 32-bit offset of the target from the beginning of its section.
199 assert(static_cast<uint64_t>(RE
.Addend
) <= UINT32_MAX
&&
200 "relocation overflow");
201 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE
.Offset
202 << " RelType: IMAGE_REL_I386_SECREL Value: "
203 << RE
.Addend
<< '\n');
204 writeBytesUnaligned(RE
.Addend
, Target
, 4);
207 llvm_unreachable("unsupported relocation type");
211 void registerEHFrames() override
{}