llvm.org GIT mirror llvm / f68eeb3
Handle relocations to thumb functions when dynamic linking COFF modules Summary: This adds the necessary logic to support relocations to thumb functions in the COFF dynamic linker. The jumps to function addresses are mostly blx, which requires the ISA selection bit when jumping to a thumb function. Note: I'm determining if the relocation requires the ISA bit when creating the relocation entries and not when resolving the relocation. I have to do that because I need the ObjectFile and the actual Symbol, which are available only when creating the entries. It would require a gross refactor if I do it otherwise, but I'm okay with doing it if you think it's better. Reviewers: peter.smith, compnerd Subscribers: rengolin, sas Differential Revision: https://reviews.llvm.org/D25151 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284410 91177308-0d34-0410-b5e6-96231b3b80d8 Walter Erquinigo 3 years ago
3 changed file(s) with 88 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
148148 /// The size of this relocation (MachO specific).
149149 unsigned Size;
150150
151 // COFF specific.
152 bool IsTargetThumbFunc;
153
151154 RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend)
152155 : SectionID(id), Offset(offset), RelType(type), Addend(addend),
153 SymOffset(0), IsPCRel(false), Size(0) {}
156 SymOffset(0), IsPCRel(false), Size(0), IsTargetThumbFunc(false) {}
154157
155158 RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend,
156159 uint64_t symoffset)
157160 : SectionID(id), Offset(offset), RelType(type), Addend(addend),
158 SymOffset(symoffset), IsPCRel(false), Size(0) {}
161 SymOffset(symoffset), IsPCRel(false), Size(0),
162 IsTargetThumbFunc(false) {}
159163
160164 RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend,
161165 bool IsPCRel, unsigned Size)
162166 : SectionID(id), Offset(offset), RelType(type), Addend(addend),
163 SymOffset(0), IsPCRel(IsPCRel), Size(Size) {}
167 SymOffset(0), IsPCRel(IsPCRel), Size(Size), IsTargetThumbFunc(false) {}
164168
165169 RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend,
166170 unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB,
167171 uint64_t SectionBOffset, bool IsPCRel, unsigned Size)
168172 : SectionID(id), Offset(offset), RelType(type),
169173 Addend(SectionAOffset - SectionBOffset + addend), IsPCRel(IsPCRel),
170 Size(Size) {
174 Size(Size), IsTargetThumbFunc(false) {
175 Sections.SectionA = SectionA;
176 Sections.SectionB = SectionB;
177 }
178
179 RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend,
180 unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB,
181 uint64_t SectionBOffset, bool IsPCRel, unsigned Size,
182 bool IsTargetThumbFunc)
183 : SectionID(id), Offset(offset), RelType(type),
184 Addend(SectionAOffset - SectionBOffset + addend), IsPCRel(IsPCRel),
185 Size(Size), IsTargetThumbFunc(IsTargetThumbFunc) {
171186 Sections.SectionA = SectionA;
172187 Sections.SectionB = SectionB;
173188 }
2020 #define DEBUG_TYPE "dyld"
2121
2222 namespace llvm {
23
24 static bool isThumbFunc(symbol_iterator Symbol, const ObjectFile &Obj,
25 section_iterator Section) {
26 Expected SymTypeOrErr = Symbol->getType();
27 if (!SymTypeOrErr) {
28 std::string Buf;
29 raw_string_ostream OS(Buf);
30 logAllUnhandledErrors(SymTypeOrErr.takeError(), OS, "");
31 OS.flush();
32 report_fatal_error(Buf);
33 }
34
35 if (*SymTypeOrErr != SymbolRef::ST_Function)
36 return false;
37
38 // We check the IMAGE_SCN_MEM_16BIT flag in the section of the symbol to tell
39 // if it's thumb or not
40 return cast(Obj).getCOFFSection(*Section)->Characteristics &
41 COFF::IMAGE_SCN_MEM_16BIT;
42 }
2343
2444 class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF {
2545 public:
91111 else
92112 return TargetSectionIDOrErr.takeError();
93113
114 // We need to find out if the relocation is relative to a thumb function
115 // so that we include the ISA selection bit when resolve the relocation
116 bool IsTargetThumbFunc = isThumbFunc(Symbol, Obj, Section);
117
94118 switch (RelType) {
95119 default: llvm_unreachable("unsupported relocation type");
96120 case COFF::IMAGE_REL_ARM_ABSOLUTE:
97121 // This relocation is ignored.
98122 break;
99 case COFF::IMAGE_REL_ARM_ADDR32:
123 case COFF::IMAGE_REL_ARM_ADDR32: {
124 RelocationEntry RE = RelocationEntry(
125 SectionID, Offset, RelType, Addend, TargetSectionID,
126 getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc);
127 addRelocationForSection(RE, TargetSectionID);
128 break;
129 }
100130 case COFF::IMAGE_REL_ARM_ADDR32NB: {
101131 RelocationEntry RE =
102132 RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
117147 break;
118148 }
119149 case COFF::IMAGE_REL_ARM_MOV32T: {
120 RelocationEntry RE =
121 RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
122 getSymbolOffset(*Symbol), 0, 0, false, 0);
150 RelocationEntry RE = RelocationEntry(
151 SectionID, Offset, RelType, Addend, TargetSectionID,
152 getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc);
123153 addRelocationForSection(RE, TargetSectionID);
124154 break;
125155 }
141171 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
142172 const auto Section = Sections[RE.SectionID];
143173 uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
174 int ISASelectionBit = RE.IsTargetThumbFunc ? 1 : 0;
144175
145176 switch (RE.RelType) {
146177 default: llvm_unreachable("unsupported relocation type");
153184 RE.Sections.SectionA == static_cast(-1)
154185 ? Value
155186 : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
187 Result |= ISASelectionBit;
156188 assert(static_cast(Result) <= INT32_MAX &&
157189 "relocation overflow");
158190 assert(static_cast(Result) >= INT32_MIN &&
177209 << " RelType: IMAGE_REL_ARM_ADDR32NB"
178210 << " TargetSection: " << RE.Sections.SectionA
179211 << " Value: " << format("0x%08" PRIx32, Result) << '\n');
212 Result |= ISASelectionBit;
180213 writeBytesUnaligned(Result, Target, 4);
181214 break;
182215 }
227260 Bytes[3] |= (((Immediate & 0x0700) >> 8) << 4);
228261 };
229262
230 EncodeImmediate(&Target[0], static_cast(Result) >> 00);
263 EncodeImmediate(&Target[0],
264 (static_cast(Result) >> 00) | ISASelectionBit);
231265 EncodeImmediate(&Target[4], static_cast(Result) >> 16);
232266
233267 break;
0 // RUN: llvm-mc -triple thumbv7-windows-itanium -filetype obj -o %t.obj %s
1 // RUN: llvm-rtdyld -triple thumbv7-windows -dummy-extern OutputDebugStringW=0x01310060 -dummy-extern OutputDebugStringA=0x78563412 -dummy-extern ExitProcess=0x54769890 -dummy-extern unnamed_addr=0x00001024 -verify -check %s %t.obj
1 // RUN: llvm-rtdyld -triple thumbv7-windows -dummy-extern OutputDebugStringW=0x01310061 -dummy-extern OutputDebugStringA=0x78563413 -dummy-extern ExitProcess=0x54769891 -dummy-extern unnamed_addr=0x00001024 -verify -check %s %t.obj
22
33 .text
44 .syntax unified
8181 __imp_OutputDebugStringA:
8282 @ rel6:
8383 .long OutputDebugStringA @ IMAGE_REL_ARM_ADDR32
84 # rtdyld-check: *{4}__imp_OutputDebugStringA = 0x78563412
84 # rtdyld-check: *{4}__imp_OutputDebugStringA = 0x78563413
8585
8686 .p2align 2
8787 __imp_ExitProcess:
8888 @ rel7:
8989 .long ExitProcess @ IMAGE_REL_ARM_ADDR32
90 # rtdyld-check: *{4}__imp_ExitProcess = 0x54769890
90 # rtdyld-check: *{4}__imp_ExitProcess = 0x54769891
9191
9292 .global relocations
9393 relocations:
117117 __imp_OutputDebugStringW:
118118 @ rel13:
119119 .long OutputDebugStringW @ IMAGE_REL_ARM_ADDR32
120 # rtdyld-check: *{4}__imp_OutputDebugStringW = 0x01310060
120 # rtdyld-check: *{4}__imp_OutputDebugStringW = 0x01310061
121121
122122 .p2align 2
123
124 branch_to_thumb_func:
125 @ rel14: @ IMAGE_REL_ARM_MOV32T
126 movw r0, :lower16:function
127 # rtdyld-check: decode_operand(branch_to_thumb_func, 1) = (function&0x0000ffff|1)
128 movt r0, :upper16:function
129 # TODO rtdyld-check: decode_operand(branch_to_thumb_func, 1) = (function&0xffff0000>>16)
130 bx r0
131 trap
132
133 .data
134
135 .p2align 2
136 a_data_symbol:
137 .long 1073741822
138
139 .p2align 2
140
141 .text
142
143 ref_to_data_symbol_addr:
144 @ rel15: @ IMAGE_REL_ARM_MOV32T
145 movw r0, :lower16:a_data_symbol
146 # rtdyld-check: decode_operand(ref_to_data_symbol_addr, 1) = (a_data_symbol&0x0000ffff)
147 movt r0, :upper16:a_data_symbol
148 # TODO rtdyld-check: decode_operand(ref_to_data_symbol_addr, 1) = (a_data_symbol&0xffff0000>>16)