OSDN Git Service

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