llvm.org GIT mirror llvm / 2bbb2bd
Handle IMAGE_REL_AMD64_ADDR32NB in RuntimeDyldCOFF Summary: IMAGE_REL_AMD64_ADDR32NB relocations are currently set to zero in all cases. This patch sets the relocation to the correct value when possible and shows an error when not. Reviewers: enderby, lhames, compnerd Reviewed By: compnerd Subscribers: LepelTsmok, compnerd, martell, llvm-commits Differential Revision: https://reviews.llvm.org/D30709 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325700 91177308-0d34-0410-b5e6-96231b3b80d8 Frederich Munch 2 years ago
2 changed file(s) with 121 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
2929 // unregisteredEH frame sections with the memory manager.
3030 SmallVector UnregisteredEHFrameSections;
3131 SmallVector RegisteredEHFrameSections;
32 uint64_t ImageBase;
33
34 // Fake an __ImageBase pointer by returning the section with the lowest adress
35 uint64_t getImageBase() {
36 if (!ImageBase) {
37 ImageBase = std::numeric_limits::max();
38 for (const SectionEntry &Section : Sections)
39 ImageBase = std::min(ImageBase, Section.getLoadAddress());
40 }
41 return ImageBase;
42 }
43
44 void write32BitOffset(uint8_t *Target, int64_t Addend, uint64_t Delta) {
45 uint64_t Result = Addend + Delta;
46 assert(Result <= UINT32_MAX && "Relocation overflow");
47 writeBytesUnaligned(Result, Target, 4);
48 }
3249
3350 public:
3451 RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM,
3552 JITSymbolResolver &Resolver)
36 : RuntimeDyldCOFF(MM, Resolver) {}
37
38 unsigned getMaxStubSize() override {
39 return 6; // 2-byte jmp instruction + 32-bit relative address
40 }
53 : RuntimeDyldCOFF(MM, Resolver), ImageBase(0) {}
54
55 unsigned getStubAlignment() override { return 1; }
56
57 // 2-byte jmp instruction + 32-bit relative address + 64-bit absolute jump
58 unsigned getMaxStubSize() override { return 14; }
4159
4260 // The target location for the relocation is described by RE.SectionID and
4361 // RE.Offset. RE.SectionID can be used to find the SectionEntry. Each
84102 }
85103
86104 case COFF::IMAGE_REL_AMD64_ADDR32NB: {
87 // Note ADDR32NB requires a well-established notion of
88 // image base. This address must be less than or equal
89 // to every section's load address, and all sections must be
90 // within a 32 bit offset from the base.
91 //
92 // For now we just set these to zero.
93 writeBytesUnaligned(0, Target, 4);
105 // ADDR32NB requires an offset less than 2GB from 'ImageBase'.
106 // The MemoryManager can make sure this is always true by forcing the
107 // memory layout to be: CodeSection < ReadOnlySection < ReadWriteSection.
108 const uint64_t ImageBase = getImageBase();
109 if (Value < ImageBase || ((Value - ImageBase) > UINT32_MAX)) {
110 llvm::errs() << "IMAGE_REL_AMD64_ADDR32NB relocation requires an"
111 << "ordered section layout.\n";
112 write32BitOffset(Target, 0, 0);
113 } else {
114 write32BitOffset(Target, RE.Addend, Value - ImageBase);
115 }
94116 break;
95117 }
96118
103125 llvm_unreachable("Relocation type not implemented yet!");
104126 break;
105127 }
128 }
129
130 std::tuple
131 generateRelocationStub(unsigned SectionID, StringRef TargetName,
132 uint64_t Offset, uint64_t RelType, uint64_t Addend,
133 StubMap &Stubs) {
134 uintptr_t StubOffset;
135 SectionEntry &Section = Sections[SectionID];
136
137 RelocationValueRef OriginalRelValueRef;
138 OriginalRelValueRef.SectionID = SectionID;
139 OriginalRelValueRef.Offset = Offset;
140 OriginalRelValueRef.Addend = Addend;
141 OriginalRelValueRef.SymbolName = TargetName.data();
142
143 auto Stub = Stubs.find(OriginalRelValueRef);
144 if (Stub == Stubs.end()) {
145 DEBUG(dbgs() << " Create a new stub function for " << TargetName.data()
146 << "\n");
147
148 StubOffset = Section.getStubOffset();
149 Stubs[OriginalRelValueRef] = StubOffset;
150 createStubFunction(Section.getAddressWithOffset(StubOffset));
151 Section.advanceStubOffset(getMaxStubSize());
152 } else {
153 DEBUG(dbgs() << " Stub function found for " << TargetName.data() << "\n");
154 StubOffset = Stub->second;
155 }
156
157 // FIXME: If RelType == COFF::IMAGE_REL_AMD64_ADDR32NB we should be able
158 // to ignore the __ImageBase requirement and just forward to the stub
159 // directly as an offset of this section:
160 // write32BitOffset(Section.getAddressWithOffset(Offset), 0, StubOffset);
161 // .xdata exception handler's aren't having this though.
162
163 // Resolve original relocation to stub function.
164 const RelocationEntry RE(SectionID, Offset, RelType, Addend);
165 resolveRelocation(RE, Section.getLoadAddressWithOffset(StubOffset));
166
167 // adjust relocation info so resolution writes to the stub function
168 Addend = 0;
169 Offset = StubOffset + 6;
170 RelType = COFF::IMAGE_REL_AMD64_ADDR64;
171
172 return std::make_tuple(Offset, RelType, Addend);
106173 }
107174
108175 Expected
130197 SectionEntry &Section = Sections[SectionID];
131198 uintptr_t ObjTarget = Section.getObjAddress() + Offset;
132199
200 Expected TargetNameOrErr = Symbol->getName();
201 if (!TargetNameOrErr)
202 return TargetNameOrErr.takeError();
203 StringRef TargetName = *TargetNameOrErr;
204
133205 switch (RelType) {
134206
135207 case COFF::IMAGE_REL_AMD64_REL32:
141213 case COFF::IMAGE_REL_AMD64_ADDR32NB: {
142214 uint8_t *Displacement = (uint8_t *)ObjTarget;
143215 Addend = readBytesUnaligned(Displacement, 4);
216
217 if (IsExtern)
218 std::tie(Offset, RelType, Addend) = generateRelocationStub(
219 SectionID, TargetName, Offset, RelType, Addend, Stubs);
220
144221 break;
145222 }
146223
153230 default:
154231 break;
155232 }
156
157 Expected TargetNameOrErr = Symbol->getName();
158 if (!TargetNameOrErr)
159 return TargetNameOrErr.takeError();
160 StringRef TargetName = *TargetNameOrErr;
161233
162234 DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
163235 << " RelType: " << RelType << " TargetName: " << TargetName
182254 return ++RelI;
183255 }
184256
185 unsigned getStubAlignment() override { return 1; }
186257 void registerEHFrames() override {
187258 for (auto const &EHFrameSID : UnregisteredEHFrameSections) {
188259 uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress();
193264 }
194265 UnregisteredEHFrameSections.clear();
195266 }
267
196268 Error finalizeLoad(const ObjectFile &Obj,
197269 ObjSectionToIDMap &SectionMap) override {
198270 // Look for and record the EH frame section IDs.
201273 StringRef Name;
202274 if (auto EC = Section.getName(Name))
203275 return errorCodeToError(EC);
204 // Note unwind info is split across .pdata and .xdata, so this
205 // may not be sufficiently general for all users.
206 if (Name == ".xdata") {
276
277 // Note unwind info is stored in .pdata but often points to .xdata
278 // with an IMAGE_REL_AMD64_ADDR32NB relocation. Using a memory manager
279 // that keeps sections ordered in relation to __ImageBase is necessary.
280 if (Name == ".pdata")
207281 UnregisteredEHFrameSections.push_back(SectionPair.second);
208 }
209282 }
210283 return Error::success();
211284 }
0 # RUN: rm -rf %t && mkdir -p %t
1 # RUN: llvm-mc -triple=x86_64-pc-win32 -filetype=obj -o %t/COFF_x86_64_IMGREL.o %s
2 # RUN: llvm-rtdyld -triple=x86_64-pc-win32 -verify -check=%s %t/COFF_x86_64_IMGREL.o
3 .text
4 .def F;
5 .scl 2;
6 .type 32;
7 .endef
8 .globl __constdata
9
10 .section .rdata, "dr", discard, __constdata
11 .align 8
12 __constdata:
13 .quad 0
14
15 .text
16 .globl F
17 .align 16, 0x90
18
19 F: # @F
20 # rtdyld-check: decode_operand(inst1, 3) = section_addr(COFF_x86_64_IMGREL.o, .text)+0
21 inst1:
22 mov %ebx, F@IMGREL
23 # rtdyld-check: decode_operand(inst2, 3) = section_addr(COFF_x86_64_IMGREL.o, .rdata)+5
24 inst2:
25 mov %ebx, (__constdata@imgrel+5)