[COFF] Add support for delay loading DLLs on ARM
Differential Revision: https://reviews.llvm.org/D35768 llvm-svn: 309017
This commit is contained in:
parent
1913360a16
commit
82eaf6cb50
@ -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, int32_t V) {
|
||||
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");
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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(DefinedImportData *S, Chunk *Dir) {
|
||||
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");
|
||||
}
|
||||
|
||||
106
lld/test/COFF/delayimports-armnt.yaml
Normal file
106
lld/test/COFF/delayimports-armnt.yaml
Normal file
@ -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
|
||||
...
|
||||
Loading…
x
Reference in New Issue
Block a user