xref: /aosp_15_r20/external/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===--- RuntimeDyldCOFFI386.h --- COFF/X86_64 specific code ---*- C++ --*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // COFF x86 support for MC-JIT runtime dynamic linker.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
15*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
16*9880d681SAndroid Build Coastguard Worker 
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/COFF.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/COFF.h"
19*9880d681SAndroid Build Coastguard Worker #include "../RuntimeDyldCOFF.h"
20*9880d681SAndroid Build Coastguard Worker 
21*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "dyld"
22*9880d681SAndroid Build Coastguard Worker 
23*9880d681SAndroid Build Coastguard Worker namespace llvm {
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF {
26*9880d681SAndroid Build Coastguard Worker public:
RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager & MM,RuntimeDyld::SymbolResolver & Resolver)27*9880d681SAndroid Build Coastguard Worker   RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM,
28*9880d681SAndroid Build Coastguard Worker                       RuntimeDyld::SymbolResolver &Resolver)
29*9880d681SAndroid Build Coastguard Worker       : RuntimeDyldCOFF(MM, Resolver) {}
30*9880d681SAndroid Build Coastguard Worker 
getMaxStubSize()31*9880d681SAndroid Build Coastguard Worker   unsigned getMaxStubSize() override {
32*9880d681SAndroid Build Coastguard Worker     return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
33*9880d681SAndroid Build Coastguard Worker   }
34*9880d681SAndroid Build Coastguard Worker 
getStubAlignment()35*9880d681SAndroid Build Coastguard Worker   unsigned getStubAlignment() override { return 1; }
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker   Expected<relocation_iterator>
processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & Obj,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)38*9880d681SAndroid Build Coastguard Worker   processRelocationRef(unsigned SectionID,
39*9880d681SAndroid Build Coastguard Worker                        relocation_iterator RelI,
40*9880d681SAndroid Build Coastguard Worker                        const ObjectFile &Obj,
41*9880d681SAndroid Build Coastguard Worker                        ObjSectionToIDMap &ObjSectionToID,
42*9880d681SAndroid Build Coastguard Worker                        StubMap &Stubs) override {
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker     auto Symbol = RelI->getSymbol();
45*9880d681SAndroid Build Coastguard Worker     if (Symbol == Obj.symbol_end())
46*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Unknown symbol in relocation");
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker     Expected<StringRef> TargetNameOrErr = Symbol->getName();
49*9880d681SAndroid Build Coastguard Worker     if (!TargetNameOrErr)
50*9880d681SAndroid Build Coastguard Worker       return TargetNameOrErr.takeError();
51*9880d681SAndroid Build Coastguard Worker     StringRef TargetName = *TargetNameOrErr;
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker     auto SectionOrErr = Symbol->getSection();
54*9880d681SAndroid Build Coastguard Worker     if (!SectionOrErr)
55*9880d681SAndroid Build Coastguard Worker       return SectionOrErr.takeError();
56*9880d681SAndroid Build Coastguard Worker     auto Section = *SectionOrErr;
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker     uint64_t RelType = RelI->getType();
59*9880d681SAndroid Build Coastguard Worker     uint64_t Offset = RelI->getOffset();
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker     // Determine the Addend used to adjust the relocation value.
62*9880d681SAndroid Build Coastguard Worker     uint64_t Addend = 0;
63*9880d681SAndroid Build Coastguard Worker     SectionEntry &AddendSection = Sections[SectionID];
64*9880d681SAndroid Build Coastguard Worker     uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
65*9880d681SAndroid Build Coastguard Worker     uint8_t *Displacement = (uint8_t *)ObjTarget;
66*9880d681SAndroid Build Coastguard Worker 
67*9880d681SAndroid Build Coastguard Worker     switch (RelType) {
68*9880d681SAndroid Build Coastguard Worker     case COFF::IMAGE_REL_I386_DIR32:
69*9880d681SAndroid Build Coastguard Worker     case COFF::IMAGE_REL_I386_DIR32NB:
70*9880d681SAndroid Build Coastguard Worker     case COFF::IMAGE_REL_I386_SECREL:
71*9880d681SAndroid Build Coastguard Worker     case COFF::IMAGE_REL_I386_REL32: {
72*9880d681SAndroid Build Coastguard Worker       Addend = readBytesUnaligned(Displacement, 4);
73*9880d681SAndroid Build Coastguard Worker       break;
74*9880d681SAndroid Build Coastguard Worker     }
75*9880d681SAndroid Build Coastguard Worker     default:
76*9880d681SAndroid Build Coastguard Worker       break;
77*9880d681SAndroid Build Coastguard Worker     }
78*9880d681SAndroid Build Coastguard Worker 
79*9880d681SAndroid Build Coastguard Worker #if !defined(NDEBUG)
80*9880d681SAndroid Build Coastguard Worker     SmallString<32> RelTypeName;
81*9880d681SAndroid Build Coastguard Worker     RelI->getTypeName(RelTypeName);
82*9880d681SAndroid Build Coastguard Worker #endif
83*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
84*9880d681SAndroid Build Coastguard Worker                  << " RelType: " << RelTypeName << " TargetName: " << TargetName
85*9880d681SAndroid Build Coastguard Worker                  << " Addend " << Addend << "\n");
86*9880d681SAndroid Build Coastguard Worker 
87*9880d681SAndroid Build Coastguard Worker     unsigned TargetSectionID = -1;
88*9880d681SAndroid Build Coastguard Worker     if (Section == Obj.section_end()) {
89*9880d681SAndroid Build Coastguard Worker       RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
90*9880d681SAndroid Build Coastguard Worker       addRelocationForSymbol(RE, TargetName);
91*9880d681SAndroid Build Coastguard Worker     } else {
92*9880d681SAndroid Build Coastguard Worker       if (auto TargetSectionIDOrErr =
93*9880d681SAndroid Build Coastguard Worker           findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
94*9880d681SAndroid Build Coastguard Worker         TargetSectionID = *TargetSectionIDOrErr;
95*9880d681SAndroid Build Coastguard Worker       else
96*9880d681SAndroid Build Coastguard Worker         return TargetSectionIDOrErr.takeError();
97*9880d681SAndroid Build Coastguard Worker 
98*9880d681SAndroid Build Coastguard Worker       switch (RelType) {
99*9880d681SAndroid Build Coastguard Worker       case COFF::IMAGE_REL_I386_ABSOLUTE:
100*9880d681SAndroid Build Coastguard Worker         // This relocation is ignored.
101*9880d681SAndroid Build Coastguard Worker         break;
102*9880d681SAndroid Build Coastguard Worker       case COFF::IMAGE_REL_I386_DIR32:
103*9880d681SAndroid Build Coastguard Worker       case COFF::IMAGE_REL_I386_DIR32NB:
104*9880d681SAndroid Build Coastguard Worker       case COFF::IMAGE_REL_I386_REL32: {
105*9880d681SAndroid Build Coastguard Worker         RelocationEntry RE =
106*9880d681SAndroid Build Coastguard Worker             RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
107*9880d681SAndroid Build Coastguard Worker                             getSymbolOffset(*Symbol), 0, 0, false, 0);
108*9880d681SAndroid Build Coastguard Worker         addRelocationForSection(RE, TargetSectionID);
109*9880d681SAndroid Build Coastguard Worker         break;
110*9880d681SAndroid Build Coastguard Worker       }
111*9880d681SAndroid Build Coastguard Worker       case COFF::IMAGE_REL_I386_SECTION: {
112*9880d681SAndroid Build Coastguard Worker         RelocationEntry RE =
113*9880d681SAndroid Build Coastguard Worker             RelocationEntry(TargetSectionID, Offset, RelType, 0);
114*9880d681SAndroid Build Coastguard Worker         addRelocationForSection(RE, TargetSectionID);
115*9880d681SAndroid Build Coastguard Worker         break;
116*9880d681SAndroid Build Coastguard Worker       }
117*9880d681SAndroid Build Coastguard Worker       case COFF::IMAGE_REL_I386_SECREL: {
118*9880d681SAndroid Build Coastguard Worker         RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
119*9880d681SAndroid Build Coastguard Worker                                              getSymbolOffset(*Symbol) + Addend);
120*9880d681SAndroid Build Coastguard Worker         addRelocationForSection(RE, TargetSectionID);
121*9880d681SAndroid Build Coastguard Worker         break;
122*9880d681SAndroid Build Coastguard Worker       }
123*9880d681SAndroid Build Coastguard Worker       default:
124*9880d681SAndroid Build Coastguard Worker         llvm_unreachable("unsupported relocation type");
125*9880d681SAndroid Build Coastguard Worker       }
126*9880d681SAndroid Build Coastguard Worker 
127*9880d681SAndroid Build Coastguard Worker     }
128*9880d681SAndroid Build Coastguard Worker 
129*9880d681SAndroid Build Coastguard Worker     return ++RelI;
130*9880d681SAndroid Build Coastguard Worker   }
131*9880d681SAndroid Build Coastguard Worker 
resolveRelocation(const RelocationEntry & RE,uint64_t Value)132*9880d681SAndroid Build Coastguard Worker   void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
133*9880d681SAndroid Build Coastguard Worker     const auto Section = Sections[RE.SectionID];
134*9880d681SAndroid Build Coastguard Worker     uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker     switch (RE.RelType) {
137*9880d681SAndroid Build Coastguard Worker     case COFF::IMAGE_REL_I386_ABSOLUTE:
138*9880d681SAndroid Build Coastguard Worker       // This relocation is ignored.
139*9880d681SAndroid Build Coastguard Worker       break;
140*9880d681SAndroid Build Coastguard Worker     case COFF::IMAGE_REL_I386_DIR32: {
141*9880d681SAndroid Build Coastguard Worker       // The target's 32-bit VA.
142*9880d681SAndroid Build Coastguard Worker       uint64_t Result =
143*9880d681SAndroid Build Coastguard Worker           RE.Sections.SectionA == static_cast<uint32_t>(-1)
144*9880d681SAndroid Build Coastguard Worker               ? Value
145*9880d681SAndroid Build Coastguard Worker               : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(
146*9880d681SAndroid Build Coastguard Worker                     RE.Addend);
147*9880d681SAndroid Build Coastguard Worker       assert(static_cast<int32_t>(Result) <= INT32_MAX &&
148*9880d681SAndroid Build Coastguard Worker              "relocation overflow");
149*9880d681SAndroid Build Coastguard Worker       assert(static_cast<int32_t>(Result) >= INT32_MIN &&
150*9880d681SAndroid Build Coastguard Worker              "relocation underflow");
151*9880d681SAndroid Build Coastguard Worker       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
152*9880d681SAndroid Build Coastguard Worker                    << " RelType: IMAGE_REL_I386_DIR32"
153*9880d681SAndroid Build Coastguard Worker                    << " TargetSection: " << RE.Sections.SectionA
154*9880d681SAndroid Build Coastguard Worker                    << " Value: " << format("0x%08" PRIx32, Result) << '\n');
155*9880d681SAndroid Build Coastguard Worker       writeBytesUnaligned(Result, Target, 4);
156*9880d681SAndroid Build Coastguard Worker       break;
157*9880d681SAndroid Build Coastguard Worker     }
158*9880d681SAndroid Build Coastguard Worker     case COFF::IMAGE_REL_I386_DIR32NB: {
159*9880d681SAndroid Build Coastguard Worker       // The target's 32-bit RVA.
160*9880d681SAndroid Build Coastguard Worker       // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
161*9880d681SAndroid Build Coastguard Worker       uint64_t Result =
162*9880d681SAndroid Build Coastguard Worker           Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) -
163*9880d681SAndroid Build Coastguard Worker           Sections[0].getLoadAddress();
164*9880d681SAndroid Build Coastguard Worker       assert(static_cast<int32_t>(Result) <= INT32_MAX &&
165*9880d681SAndroid Build Coastguard Worker              "relocation overflow");
166*9880d681SAndroid Build Coastguard Worker       assert(static_cast<int32_t>(Result) >= INT32_MIN &&
167*9880d681SAndroid Build Coastguard Worker              "relocation underflow");
168*9880d681SAndroid Build Coastguard Worker       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
169*9880d681SAndroid Build Coastguard Worker                    << " RelType: IMAGE_REL_I386_DIR32NB"
170*9880d681SAndroid Build Coastguard Worker                    << " TargetSection: " << RE.Sections.SectionA
171*9880d681SAndroid Build Coastguard Worker                    << " Value: " << format("0x%08" PRIx32, Result) << '\n');
172*9880d681SAndroid Build Coastguard Worker       writeBytesUnaligned(Result, Target, 4);
173*9880d681SAndroid Build Coastguard Worker       break;
174*9880d681SAndroid Build Coastguard Worker     }
175*9880d681SAndroid Build Coastguard Worker     case COFF::IMAGE_REL_I386_REL32: {
176*9880d681SAndroid Build Coastguard Worker       // 32-bit relative displacement to the target.
177*9880d681SAndroid Build Coastguard Worker       uint64_t Result = RE.Sections.SectionA == static_cast<uint32_t>(-1)
178*9880d681SAndroid Build Coastguard Worker                             ? Value
179*9880d681SAndroid Build Coastguard Worker                             : Sections[RE.Sections.SectionA].getLoadAddress();
180*9880d681SAndroid Build Coastguard Worker       Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset;
181*9880d681SAndroid Build Coastguard Worker       assert(static_cast<int32_t>(Result) <= INT32_MAX &&
182*9880d681SAndroid Build Coastguard Worker              "relocation overflow");
183*9880d681SAndroid Build Coastguard Worker       assert(static_cast<int32_t>(Result) >= INT32_MIN &&
184*9880d681SAndroid Build Coastguard Worker              "relocation underflow");
185*9880d681SAndroid Build Coastguard Worker       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
186*9880d681SAndroid Build Coastguard Worker                    << " RelType: IMAGE_REL_I386_REL32"
187*9880d681SAndroid Build Coastguard Worker                    << " TargetSection: " << RE.Sections.SectionA
188*9880d681SAndroid Build Coastguard Worker                    << " Value: " << format("0x%08" PRIx32, Result) << '\n');
189*9880d681SAndroid Build Coastguard Worker       writeBytesUnaligned(Result, Target, 4);
190*9880d681SAndroid Build Coastguard Worker       break;
191*9880d681SAndroid Build Coastguard Worker     }
192*9880d681SAndroid Build Coastguard Worker     case COFF::IMAGE_REL_I386_SECTION:
193*9880d681SAndroid Build Coastguard Worker       // 16-bit section index of the section that contains the target.
194*9880d681SAndroid Build Coastguard Worker       assert(static_cast<int32_t>(RE.SectionID) <= INT16_MAX &&
195*9880d681SAndroid Build Coastguard Worker              "relocation overflow");
196*9880d681SAndroid Build Coastguard Worker       assert(static_cast<int32_t>(RE.SectionID) >= INT16_MIN &&
197*9880d681SAndroid Build Coastguard Worker              "relocation underflow");
198*9880d681SAndroid Build Coastguard Worker       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
199*9880d681SAndroid Build Coastguard Worker                    << " RelType: IMAGE_REL_I386_SECTION Value: " << RE.SectionID
200*9880d681SAndroid Build Coastguard Worker                    << '\n');
201*9880d681SAndroid Build Coastguard Worker       writeBytesUnaligned(RE.SectionID, Target, 2);
202*9880d681SAndroid Build Coastguard Worker       break;
203*9880d681SAndroid Build Coastguard Worker     case COFF::IMAGE_REL_I386_SECREL:
204*9880d681SAndroid Build Coastguard Worker       // 32-bit offset of the target from the beginning of its section.
205*9880d681SAndroid Build Coastguard Worker       assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX &&
206*9880d681SAndroid Build Coastguard Worker              "relocation overflow");
207*9880d681SAndroid Build Coastguard Worker       assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
208*9880d681SAndroid Build Coastguard Worker              "relocation underflow");
209*9880d681SAndroid Build Coastguard Worker       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
210*9880d681SAndroid Build Coastguard Worker                    << " RelType: IMAGE_REL_I386_SECREL Value: " << RE.Addend
211*9880d681SAndroid Build Coastguard Worker                    << '\n');
212*9880d681SAndroid Build Coastguard Worker       writeBytesUnaligned(RE.Addend, Target, 2);
213*9880d681SAndroid Build Coastguard Worker       break;
214*9880d681SAndroid Build Coastguard Worker     default:
215*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("unsupported relocation type");
216*9880d681SAndroid Build Coastguard Worker     }
217*9880d681SAndroid Build Coastguard Worker   }
218*9880d681SAndroid Build Coastguard Worker 
registerEHFrames()219*9880d681SAndroid Build Coastguard Worker   void registerEHFrames() override {}
deregisterEHFrames()220*9880d681SAndroid Build Coastguard Worker   void deregisterEHFrames() override {}
221*9880d681SAndroid Build Coastguard Worker };
222*9880d681SAndroid Build Coastguard Worker 
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker 
225*9880d681SAndroid Build Coastguard Worker #endif
226*9880d681SAndroid Build Coastguard Worker 
227