diff options
Diffstat (limited to 'contrib/llvm/tools/lld/COFF/DLL.cpp')
| -rw-r--r-- | contrib/llvm/tools/lld/COFF/DLL.cpp | 67 |
1 files changed, 58 insertions, 9 deletions
diff --git a/contrib/llvm/tools/lld/COFF/DLL.cpp b/contrib/llvm/tools/lld/COFF/DLL.cpp index d76410b67471..195839139670 100644 --- a/contrib/llvm/tools/lld/COFF/DLL.cpp +++ b/contrib/llvm/tools/lld/COFF/DLL.cpp @@ -61,7 +61,7 @@ private: // A chunk for the import descriptor table. class LookupChunk : public Chunk { public: - explicit LookupChunk(Chunk *C) : HintName(C) {} + explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = ptrSize(); } size_t getSize() const override { return ptrSize(); } void writeTo(uint8_t *Buf) const override { @@ -76,7 +76,7 @@ public: // See Microsoft PE/COFF spec 7.1. Import Header for details. class OrdinalOnlyChunk : public Chunk { public: - explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {} + explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { Alignment = ptrSize(); } size_t getSize() const override { return ptrSize(); } void writeTo(uint8_t *Buf) const override { @@ -117,7 +117,6 @@ public: explicit NullChunk(size_t N) : Size(N) {} bool hasData() const override { return false; } size_t getSize() const override { return Size; } - void setAlign(size_t N) { Align = N; } private: size_t Size; @@ -215,6 +214,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,17 +274,45 @@ 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: - explicit DelayAddressChunk(Chunk *C) : Thunk(C) {} + explicit DelayAddressChunk(Chunk *C) : Thunk(C) { Alignment = ptrSize(); } size_t getSize() const override { return ptrSize(); } void writeTo(uint8_t *Buf) const override { 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); } } @@ -319,12 +362,16 @@ public: size_t getSize() const override { return Size * 4; } void writeTo(uint8_t *Buf) const override { - for (Export &E : Config->Exports) { + for (const Export &E : Config->Exports) { uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4; + uint32_t Bit = 0; + // Pointer to thumb code must have the LSB set, so adjust it. + if (Config->Machine == ARMNT && !E.Data) + Bit = 1; if (E.ForwardChunk) { - write32le(P, E.ForwardChunk->getRVA()); + write32le(P, E.ForwardChunk->getRVA() | Bit); } else { - write32le(P, cast<Defined>(E.Sym)->getRVA()); + write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit); } } } @@ -487,7 +534,7 @@ void DelayLoadContents::create(Defined *H) { for (int I = 0, E = Syms.size(); I < E; ++I) Syms[I]->setLocation(Addresses[Base + I]); auto *MH = make<NullChunk>(8); - MH->setAlign(8); + MH->Alignment = 8; ModuleHandles.push_back(MH); // Fill the delay import table header fields. @@ -506,6 +553,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"); } |
