[lld] r309017 - [COFF] Add support for delay loading DLLs on ARM
Martin Storsjo via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 25 13:00:37 PDT 2017
Author: mstorsjo
Date: Tue Jul 25 13:00:37 2017
New Revision: 309017
URL: http://llvm.org/viewvc/llvm-project?rev=309017&view=rev
Log:
[COFF] Add support for delay loading DLLs on ARM
Differential Revision: https://reviews.llvm.org/D35768
Added:
lld/trunk/test/COFF/delayimports-armnt.yaml
Modified:
lld/trunk/COFF/Chunks.cpp
lld/trunk/COFF/Chunks.h
lld/trunk/COFF/DLL.cpp
Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=309017&r1=309016&r2=309017&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Tue Jul 25 13:00:37 2017
@@ -119,7 +119,7 @@ static uint16_t readMOV(uint8_t *Off) {
return Imm;
}
-static void applyMOV32T(uint8_t *Off, uint32_t V) {
+void applyMOV32T(uint8_t *Off, uint32_t V) {
uint16_t ImmW = readMOV(Off); // read MOVW operand
uint16_t ImmT = readMOV(Off + 4); // read MOVT operand
uint32_t Imm = ImmW | (ImmT << 16);
@@ -136,7 +136,7 @@ static void applyBranch20T(uint8_t *Off,
or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff));
}
-static void applyBranch24T(uint8_t *Off, int32_t V) {
+void applyBranch24T(uint8_t *Off, int32_t V) {
if (!isInt<25>(V))
fatal("relocation out of range");
uint32_t S = V < 0 ? 1 : 0;
@@ -496,6 +496,7 @@ uint8_t Baserel::getDefaultType() {
case AMD64:
return IMAGE_REL_BASED_DIR64;
case I386:
+ case ARMNT:
return IMAGE_REL_BASED_HIGHLOW;
default:
llvm_unreachable("unknown machine type");
Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=309017&r1=309016&r2=309017&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Tue Jul 25 13:00:37 2017
@@ -369,6 +369,9 @@ public:
uint8_t Type;
};
+void applyMOV32T(uint8_t *Off, uint32_t V);
+void applyBranch24T(uint8_t *Off, int32_t V);
+
} // namespace coff
} // namespace lld
Modified: lld/trunk/COFF/DLL.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.cpp?rev=309017&r1=309016&r2=309017&view=diff
==============================================================================
--- lld/trunk/COFF/DLL.cpp (original)
+++ lld/trunk/COFF/DLL.cpp Tue Jul 25 13:00:37 2017
@@ -215,6 +215,22 @@ static const uint8_t ThunkX86[] = {
0xFF, 0xE0, // jmp eax
};
+static const uint8_t ThunkARM[] = {
+ 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 __imp_<FUNCNAME>
+ 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_<FUNCNAME>
+ 0x2d, 0xe9, 0x0f, 0x48, // push.w {r0, r1, r2, r3, r11, lr}
+ 0x0d, 0xf2, 0x10, 0x0b, // addw r11, sp, #16
+ 0x2d, 0xed, 0x10, 0x0b, // vpush {d0, d1, d2, d3, d4, d5, d6, d7}
+ 0x61, 0x46, // mov r1, ip
+ 0x40, 0xf2, 0x00, 0x00, // mov.w r0, #0 DELAY_IMPORT_DESCRIPTOR
+ 0xc0, 0xf2, 0x00, 0x00, // mov.t r0, #0 DELAY_IMPORT_DESCRIPTOR
+ 0x00, 0xf0, 0x00, 0xd0, // bl #0 __delayLoadHelper2
+ 0x84, 0x46, // mov ip, r0
+ 0xbd, 0xec, 0x10, 0x0b, // vpop {d0, d1, d2, d3, d4, d5, d6, d7}
+ 0xbd, 0xe8, 0x0f, 0x48, // pop.w {r0, r1, r2, r3, r11, lr}
+ 0x60, 0x47, // bx ip
+};
+
// A chunk for the delay import thunk.
class ThunkChunkX64 : public Chunk {
public:
@@ -259,6 +275,30 @@ public:
Defined *Helper = nullptr;
};
+class ThunkChunkARM : public Chunk {
+public:
+ ThunkChunkARM(Defined *I, Chunk *D, Defined *H)
+ : Imp(I), Desc(D), Helper(H) {}
+
+ size_t getSize() const override { return sizeof(ThunkARM); }
+
+ void writeTo(uint8_t *Buf) const override {
+ memcpy(Buf + OutputSectionOff, ThunkARM, sizeof(ThunkARM));
+ applyMOV32T(Buf + OutputSectionOff + 0, Imp->getRVA() + Config->ImageBase);
+ applyMOV32T(Buf + OutputSectionOff + 22, Desc->getRVA() + Config->ImageBase);
+ applyBranch24T(Buf + OutputSectionOff + 30, Helper->getRVA() - RVA - 34);
+ }
+
+ void getBaserels(std::vector<Baserel> *Res) override {
+ Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T);
+ Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T);
+ }
+
+ Defined *Imp = nullptr;
+ Chunk *Desc = nullptr;
+ Defined *Helper = nullptr;
+};
+
// A chunk for the import descriptor table.
class DelayAddressChunk : public Chunk {
public:
@@ -269,7 +309,11 @@ public:
if (Config->is64()) {
write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
} else {
- write32le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
+ uint32_t Bit = 0;
+ // Pointer to thumb code must have the LSB set, so adjust it.
+ if (Config->Machine == ARMNT)
+ Bit = 1;
+ write32le(Buf + OutputSectionOff, (Thunk->getRVA() + Config->ImageBase) | Bit);
}
}
@@ -510,6 +554,8 @@ Chunk *DelayLoadContents::newThunkChunk(
return make<ThunkChunkX64>(S, Dir, Helper);
case I386:
return make<ThunkChunkX86>(S, Dir, Helper);
+ case ARMNT:
+ return make<ThunkChunkARM>(S, Dir, Helper);
default:
llvm_unreachable("unsupported machine type");
}
Added: lld/trunk/test/COFF/delayimports-armnt.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/delayimports-armnt.yaml?rev=309017&view=auto
==============================================================================
--- lld/trunk/test/COFF/delayimports-armnt.yaml (added)
+++ lld/trunk/test/COFF/delayimports-armnt.yaml Tue Jul 25 13:00:37 2017
@@ -0,0 +1,106 @@
+# REQUIRES: arm
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link %t.obj %p/Inputs/library.lib /subsystem:console \
+# RUN: /entry:mainCRTStartup /alternatename:__delayLoadHelper2=mainCRTStartup \
+# RUN: /delayload:library.dll /out:%t.exe
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
+# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
+# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s
+
+# IMPORT: Format: COFF-ARM
+# IMPORT-NEXT: Arch: thumb
+# IMPORT-NEXT: AddressSize: 32bit
+# IMPORT-NEXT: DelayImport {
+# IMPORT-NEXT: Name: library.dll
+# IMPORT-NEXT: Attributes: 0x1
+# IMPORT-NEXT: ModuleHandle: 0x3000
+# IMPORT-NEXT: ImportAddressTable: 0x3008
+# IMPORT-NEXT: ImportNameTable: 0x2040
+# IMPORT-NEXT: BoundDelayImportTable: 0x0
+# IMPORT-NEXT: UnloadDelayImportTable: 0x0
+# IMPORT-NEXT: Import {
+# IMPORT-NEXT: Symbol: function (0)
+# IMPORT-NEXT: Address: 0x401019
+# IMPORT-NEXT: }
+# IMPORT-NEXT: }
+#
+# BASEREL: BaseReloc [
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: ARM_MOV32(T)
+# BASEREL-NEXT: Address: 0x1000
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: ARM_MOV32(T)
+# BASEREL-NEXT: Address: 0x100C
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: ARM_MOV32(T)
+# BASEREL-NEXT: Address: 0x1018
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: ARM_MOV32(T)
+# BASEREL-NEXT: Address: 0x102E
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: HIGHLOW
+# BASEREL-NEXT: Address: 0x3008
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: ABSOLUTE
+# BASEREL-NEXT: Address: 0x3000
+# BASEREL-NEXT: }
+# BASEREL-NEXT: ]
+#
+# DISASM: 401018: 43 f2 08 0c movw r12, #12296
+# DISASM-NEXT: 40101c: c0 f2 40 0c movt r12, #64
+# DISASM-NEXT: 401020: 2d e9 0f 48 push.w {r0, r1, r2, r3, r11, lr}
+# DISASM-NEXT: 401024: 0d f2 10 0b addw r11, sp, #16
+# DISASM-NEXT: 401028: 2d ed 10 0b vpush {d0, d1, d2, d3, d4, d5, d6, d7}
+# DISASM-NEXT: 40102c: 61 46 mov r1, r12
+# DISASM-NEXT: 40102e: 42 f2 00 00 movw r0, #8192
+# DISASM-NEXT: 401032: c0 f2 40 00 movt r0, #64
+# DISASM-NEXT: 401036: ff f7 e3 ff bl #-58
+# DISASM-NEXT: 40103a: 84 46 mov r12, r0
+# DISASM-NEXT: 40103c: bd ec 10 0b vpop {d0, d1, d2, d3, d4, d5, d6, d7}
+# DISASM-NEXT: 401040: bd e8 0f 48 pop.w {r0, r1, r2, r3, r11, lr}
+# DISASM-NEXT: 401044: 60 47 bx r12
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_ARMNT
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 40F20000C0F2000000680047
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: __imp_function
+ Type: 17
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 12
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: mainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __imp_function
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
More information about the llvm-commits
mailing list