llvm.org GIT mirror llvm / 7fb0066
ExecutionEngine: add preliminary support for COFF ARM This adds rudimentary support for COFF ARM to the dynamic loader for the exeuction engine. This can be used by lldb to JIT code into a COFF ARM environment. This lays the foundation for the loader, though a few of the relocation types are yet unhandled. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273682 91177308-0d34-0410-b5e6-96231b3b80d8 Saleem Abdulrasool 4 years ago
3 changed file(s) with 401 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
1212
1313 #include "RuntimeDyldCOFF.h"
1414 #include "Targets/RuntimeDyldCOFFI386.h"
15 #include "Targets/RuntimeDyldCOFFThumb.h"
1516 #include "Targets/RuntimeDyldCOFFX86_64.h"
1617 #include "llvm/ADT/STLExtras.h"
1718 #include "llvm/ADT/Triple.h"
4445 RuntimeDyld::MemoryManager &MemMgr,
4546 RuntimeDyld::SymbolResolver &Resolver) {
4647 switch (Arch) {
47 default:
48 llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
49 break;
48 default: llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
5049 case Triple::x86:
5150 return make_unique(MemMgr, Resolver);
51 case Triple::thumb:
52 return make_unique(MemMgr, Resolver);
5253 case Triple::x86_64:
5354 return make_unique(MemMgr, Resolver);
5455 }
5657
5758 std::unique_ptr
5859 RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) {
59 if (auto ObjSectionToIDOrErr = loadObjectImpl(O))
60 if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) {
6061 return llvm::make_unique(*this, *ObjSectionToIDOrErr);
61 else {
62 } else {
6263 HasError = true;
6364 raw_string_ostream ErrStream(ErrorStr);
6465 logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, "");
0 //===--- RuntimeDyldCOFFThumb.h --- COFF/Thumb specific code ---*- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // COFF thumb support for MC-JIT runtime dynamic linker.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H
14 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H
15
16 #include "llvm/Object/COFF.h"
17 #include "llvm/Support/COFF.h"
18 #include "../RuntimeDyldCOFF.h"
19
20 #define DEBUG_TYPE "dyld"
21
22 namespace llvm {
23
24 class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF {
25 public:
26 RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM,
27 RuntimeDyld::SymbolResolver &Resolver)
28 : RuntimeDyldCOFF(MM, Resolver) {}
29
30 unsigned getMaxStubSize() override {
31 return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding
32 }
33
34 unsigned getStubAlignment() override { return 1; }
35
36 Expected
37 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 TargetNameOrErr = Symbol->getName();
47 if (!TargetNameOrErr)
48 return TargetNameOrErr.takeError();
49 StringRef TargetName = *TargetNameOrErr;
50
51 auto SectionOrErr = Symbol->getSection();
52 if (!SectionOrErr)
53 return SectionOrErr.takeError();
54 auto Section = *SectionOrErr;
55
56 uint64_t RelType = RelI->getType();
57 uint64_t Offset = RelI->getOffset();
58
59 // Determine the Addend used to adjust the relocation value.
60 uint64_t Addend = 0;
61 SectionEntry &AddendSection = Sections[SectionID];
62 uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
63 uint8_t *Displacement = (uint8_t *)ObjTarget;
64
65 switch (RelType) {
66 case COFF::IMAGE_REL_ARM_ADDR32:
67 case COFF::IMAGE_REL_ARM_ADDR32NB:
68 case COFF::IMAGE_REL_ARM_SECREL:
69 Addend = readBytesUnaligned(Displacement, 4);
70 break;
71 default:
72 break;
73 }
74
75 #if !defined(NDEBUG)
76 SmallString<32> RelTypeName;
77 RelI->getTypeName(RelTypeName);
78 #endif
79 DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
80 << " RelType: " << RelTypeName << " TargetName: " << TargetName
81 << " Addend " << Addend << "\n");
82
83 unsigned TargetSectionID = -1;
84 if (Section == Obj.section_end()) {
85 RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
86 addRelocationForSymbol(RE, TargetName);
87 } else {
88 if (auto TargetSectionIDOrErr =
89 findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
90 TargetSectionID = *TargetSectionIDOrErr;
91 else
92 return TargetSectionIDOrErr.takeError();
93
94 switch (RelType) {
95 default: llvm_unreachable("unsupported relocation type");
96 case COFF::IMAGE_REL_ARM_ABSOLUTE:
97 // This relocation is ignored.
98 break;
99 case COFF::IMAGE_REL_ARM_ADDR32:
100 case COFF::IMAGE_REL_ARM_ADDR32NB: {
101 RelocationEntry RE =
102 RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
103 getSymbolOffset(*Symbol), 0, 0, false, 0);
104 addRelocationForSection(RE, TargetSectionID);
105 break;
106 }
107 case COFF::IMAGE_REL_ARM_SECTION: {
108 RelocationEntry RE =
109 RelocationEntry(TargetSectionID, Offset, RelType, 0);
110 addRelocationForSection(RE, TargetSectionID);
111 break;
112 }
113 case COFF::IMAGE_REL_ARM_SECREL: {
114 RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
115 getSymbolOffset(*Symbol) + Addend);
116 addRelocationForSection(RE, TargetSectionID);
117 break;
118 }
119 case COFF::IMAGE_REL_ARM_MOV32T: {
120 RelocationEntry RE =
121 RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
122 getSymbolOffset(*Symbol), 0, 0, false, 0);
123 addRelocationForSection(RE, TargetSectionID);
124 break;
125 }
126 case COFF::IMAGE_REL_ARM_BRANCH20T:
127 case COFF::IMAGE_REL_ARM_BRANCH24T:
128 case COFF::IMAGE_REL_ARM_BLX23T: {
129 RelocationEntry RE =
130 RelocationEntry(SectionID, Offset, RelType,
131 getSymbolOffset(*Symbol) + Addend, true, 0);
132 addRelocationForSection(RE, TargetSectionID);
133 break;
134 }
135 }
136 }
137
138 return ++RelI;
139 }
140
141 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
142 const auto Section = Sections[RE.SectionID];
143 uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
144
145 switch (RE.RelType) {
146 default: llvm_unreachable("unsupported relocation type");
147 case COFF::IMAGE_REL_ARM_ABSOLUTE:
148 // This relocation is ignored.
149 break;
150 case COFF::IMAGE_REL_ARM_ADDR32: {
151 // The target's 32-bit VA.
152 uint64_t Result =
153 RE.Sections.SectionA == static_cast(-1)
154 ? Value
155 : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
156 assert(static_cast(Result) <= INT32_MAX &&
157 "relocation overflow");
158 assert(static_cast(Result) >= INT32_MIN &&
159 "relocation underflow");
160 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
161 << " RelType: IMAGE_REL_ARM_ADDR32"
162 << " TargetSection: " << RE.Sections.SectionA
163 << " Value: " << format("0x%08" PRIx32, Result) << '\n');
164 writeBytesUnaligned(Result, Target, 4);
165 break;
166 }
167 case COFF::IMAGE_REL_ARM_ADDR32NB: {
168 // The target's 32-bit RVA.
169 // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
170 uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() -
171 Sections[0].getLoadAddress() + RE.Addend;
172 assert(static_cast(Result) <= INT32_MAX &&
173 "relocation overflow");
174 assert(static_cast(Result) >= INT32_MIN &&
175 "relocation underflow");
176 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
177 << " RelType: IMAGE_REL_ARM_ADDR32NB"
178 << " TargetSection: " << RE.Sections.SectionA
179 << " Value: " << format("0x%08" PRIx32, Result) << '\n');
180 writeBytesUnaligned(Result, Target, 4);
181 break;
182 }
183 case COFF::IMAGE_REL_ARM_SECTION:
184 // 16-bit section index of the section that contains the target.
185 assert(static_cast(RE.SectionID) <= INT16_MAX &&
186 "relocation overflow");
187 assert(static_cast(RE.SectionID) >= INT16_MIN &&
188 "relocation underflow");
189 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
190 << " RelType: IMAGE_REL_ARM_SECTION Value: " << RE.SectionID
191 << '\n');
192 writeBytesUnaligned(RE.SectionID, Target, 2);
193 break;
194 case COFF::IMAGE_REL_ARM_SECREL:
195 // 32-bit offset of the target from the beginning of its section.
196 assert(static_cast(RE.Addend) <= INT32_MAX &&
197 "relocation overflow");
198 assert(static_cast(RE.Addend) >= INT32_MIN &&
199 "relocation underflow");
200 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
201 << " RelType: IMAGE_REL_ARM_SECREL Value: " << RE.Addend
202 << '\n');
203 writeBytesUnaligned(RE.Addend, Target, 2);
204 break;
205 case COFF::IMAGE_REL_ARM_MOV32T: {
206 // 32-bit VA of the target applied to a contiguous MOVW+MOVT pair.
207 uint64_t Result =
208 Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
209 assert(static_cast(Result) <= INT32_MAX &&
210 "relocation overflow");
211 assert(static_cast(Result) >= INT32_MIN &&
212 "relocation underflow");
213 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
214 << " RelType: IMAGE_REL_ARM_MOV32T"
215 << " TargetSection: " << RE.Sections.SectionA
216 << " Value: " << format("0x%08" PRIx32, Result) << '\n');
217
218 // MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8|
219 // imm32 = zext imm4:i:imm3:imm8
220 // MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8|
221 // imm16 = imm4:i:imm3:imm8
222
223 auto EncodeImmediate = [](uint8_t *Bytes, uint16_t Immediate) {
224 Bytes[0] |= ((Immediate & 0xf000) >> 12);
225 Bytes[1] |= ((Immediate & 0x0800) >> 11);
226 Bytes[2] |= ((Immediate & 0x00ff) >> 0);
227 Bytes[3] |= ((Immediate & 0x0700) >> 8);
228 };
229
230 EncodeImmediate(&Target[0], static_cast(Result) >> 00);
231 EncodeImmediate(&Target[4], static_cast(Result) >> 16);
232
233 break;
234 }
235 case COFF::IMAGE_REL_ARM_BRANCH20T: {
236 // The most significant 20-bits of the signed 21-bit relative displacement
237 uint64_t Value =
238 RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
239 assert(static_cast(RE.Addend) <= INT32_MAX &&
240 "relocation overflow");
241 assert(static_cast(RE.Addend) >= INT32_MIN &&
242 "relocation underflow");
243 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
244 << " RelType: IMAGE_REL_ARM_BRANCH20T"
245 << " Value: " << static_cast(Value) << '\n');
246 llvm_unreachable("unimplemented relocation");
247 break;
248 }
249 case COFF::IMAGE_REL_ARM_BRANCH24T: {
250 // The most significant 24-bits of the signed 25-bit relative displacement
251 uint64_t Value =
252 RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
253 assert(static_cast(RE.Addend) <= INT32_MAX &&
254 "relocation overflow");
255 assert(static_cast(RE.Addend) >= INT32_MIN &&
256 "relocation underflow");
257 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
258 << " RelType: IMAGE_REL_ARM_BRANCH24T"
259 << " Value: " << static_cast(Value) << '\n');
260 llvm_unreachable("unimplemented relocation");
261 break;
262 }
263 case COFF::IMAGE_REL_ARM_BLX23T: {
264 // The most significant 24-bits of the signed 25-bit relative displacement
265 uint64_t Value =
266 RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
267 assert(static_cast(RE.Addend) <= INT32_MAX &&
268 "relocation overflow");
269 assert(static_cast(RE.Addend) >= INT32_MIN &&
270 "relocation underflow");
271 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
272 << " RelType: IMAGE_REL_ARM_BLX23T"
273 << " Value: " << static_cast(Value) << '\n');
274 llvm_unreachable("unimplemented relocation");
275 break;
276 }
277 }
278 }
279
280 void registerEHFrames() override {}
281 void deregisterEHFrames() override {}
282 };
283
284 }
285
286 #endif
287
0 // RUN: llvm-mc -triple thumbv7-windows-itanium -filetype obj -o %t.obj %s
1 // RUN: llvm-rtdyld -triple thumbv7-windows -dummy-extern OutputDebugStringA=0x78563412 -dummy-extern ExitProcess=0x54769890 -dummy-extern unnamed_addr=0x00001024 -verify -check %s %t.obj
2
3 .text
4 .syntax unified
5
6 .def unnamed_addr
7 .scl 2
8 .type 32
9 .endef
10 .global unnamed_addr
11
12 .def branch24t
13 .scl 2
14 .type 32
15 .endef
16 .global branch24t
17 .p2align 1
18 .code 16
19 .thumb_func
20 branch24t:
21 @ rel1:
22 # b unnamed_addr @ IMAGE_REL_ARM_BRANCH24T
23
24 .def function
25 .scl 2
26 .type 32
27 .endef
28 .globl function
29 .p2align 1
30 .code 16
31 .thumb_func
32 function:
33 push.w {r11, lr}
34 mov r11, sp
35 rel2: @ IMAGE_REL_ARM_MOV32T
36 movw r0, :lower16:__imp_OutputDebugStringA
37 # rtdyld-check: decode_operand(rel2, 1) = (__imp_OutputDebugStringA&0x0000ffff)
38 movt r0, :upper16:__imp_OutputDebugStringA
39 # TODO rtdyld-check: decode_operand(rel2, 1) = (__imp_OutputDebugStringA&0xffff0000>>16)
40 ldr r1, [r0]
41 rel3: @ IMAGE_REL_ARM_MOV32T
42 movw r0, :lower16:string
43 # rtdyld-check: decode_operand(rel3, 1) = (string&0x0000ffff)
44 movt r0, :upper16:string
45 # TODO rtdyld-check: decode_operand(rel3, 1) = (string&0xffff0000>>16)
46 blx r1
47 rel4: @ IMAGE_REL_ARM_MOV32T
48 movw r0, :lower16:__imp_ExitProcess
49 # rtdyld-check: decode_operand(rel4, 1) = (__imp_ExitProcess&0x0000ffff)
50 movt r0, :upper16:__imp_ExitProcess
51 # TODO rtdyld-check: decode_operand(rel4, 1) = (__imp_ExitProcess&0xffff0000>>16)
52 ldr r1, [r0]
53 movs r0, #0
54 pop.w {r11, lr}
55 bx r1
56
57 .def main
58 .scl 2
59 .type 32
60 .endef
61 .globl main
62 .p2align 1
63 .code 16
64 .thumb_func
65 main:
66 push.w {r11, lr}
67 mov r11, sp
68 rel5:
69 # bl function @ IMAGE_REL_ARM_BLX23T
70 movs r0, #0
71 pop.w {r11, pc}
72
73 .section .rdata,"dr"
74 .global string
75 string:
76 .asciz "Hello World\n"
77
78 .data
79
80 .p2align 2
81 __imp_OutputDebugStringA:
82 @ rel6:
83 .long OutputDebugStringA @ IMAGE_REL_ARM_ADDR32
84 # rtdyld-check: *{4}__imp_OutputDebugStringA = 0x78563412
85
86 .p2align 2
87 __imp_ExitProcess:
88 @ rel7:
89 .long ExitProcess @ IMAGE_REL_ARM_ADDR32
90 # rtdyld-check: *{4}__imp_ExitProcess = 0x54769890
91
92 .global relocations
93 relocations:
94 @ rel8:
95 .long function(imgrel) @ IMAGE_REL_ARM_ADDR32NB
96 # rtdyld-check: *{4}relocations = function - section_addr(COFF_Thumb.s.tmp.obj, .text)
97 rel9:
98 .secidx __imp_OutputDebugStringA @ IMAGE_REL_ARM_SECTION
99 # rtdyld-check: *{2}rel9 = 1
100 rel10:
101 .long relocations(secrel32) @ IMAGE_REL_ARM_SECREL
102 # rtdyld-check: *{4}rel10 = relocations - section_addr(COFF_Thumb.s.tmp.obj, .data)
103 rel11:
104 .secrel32 relocations @ IMAGE_REL_ARM_SECREL
105 # rtdyld-check: *{4}rel11 = relocations - section_addr(COFF_Thumb.s.tmp.obj, .data)
106