[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