From 382dc96e29d989cb30407230c70cb3eeac8b11d2 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Fri, 26 Jun 2015 21:40:15 +0000 Subject: COFF: Fix delay-import tables. There were a few issues with the previous delay-import tables. - "Attribute" field should have been 1 instead of 0. (I don't know the meaning of this field, though.) - LEA and CALL operands had wrong addresses. - Address tables are in .didat (which is read-only). They should have been in .data. llvm-svn: 240837 --- lld/COFF/DLL.cpp | 60 +++++++++++++++++++++++++++++++++++------------------ lld/COFF/DLL.h | 6 +++--- lld/COFF/Writer.cpp | 9 ++++---- 3 files changed, 48 insertions(+), 27 deletions(-) (limited to 'lld/COFF') diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp index 188674874df0..9d5eb817220a 100644 --- a/lld/COFF/DLL.cpp +++ b/lld/COFF/DLL.cpp @@ -228,6 +228,7 @@ public: void writeTo(uint8_t *Buf) override { auto *E = (delay_import_directory_table_entry *)(Buf + FileOff); + E->Attributes = 1; E->Name = DLLName->getRVA(); E->ModuleHandle = ModuleHandle->getRVA(); E->DelayImportAddressTable = AddressTab->getRVA(); @@ -272,15 +273,14 @@ static const uint8_t Thunk[] = { // A chunk for the delay import thunk. class ThunkChunk : public Chunk { public: - ThunkChunk(Defined *I, Defined *H) : Imp(I), Helper(H) {} - + ThunkChunk(Defined *I, Chunk *D, Defined *H) : Imp(I), Desc(D), Helper(H) {} size_t getSize() const override { return sizeof(Thunk); } void writeTo(uint8_t *Buf) override { memcpy(Buf + FileOff, Thunk, sizeof(Thunk)); - write32le(Buf + FileOff + 36, Imp->getRVA()); - write32le(Buf + FileOff + 43, Desc->getRVA()); - write32le(Buf + FileOff + 48, Helper->getRVA()); + write32le(Buf + FileOff + 36, Imp->getRVA() - RVA - 40); + write32le(Buf + FileOff + 43, Desc->getRVA() - RVA - 47); + write32le(Buf + FileOff + 48, Helper->getRVA() - RVA - 52); } Defined *Imp = nullptr; @@ -288,14 +288,10 @@ public: Defined *Helper = nullptr; }; -std::vector DelayLoadContents::getChunks(Defined *H) { - Helper = H; - create(); +std::vector DelayLoadContents::getChunks() { std::vector V; for (std::unique_ptr &C : Dirs) V.push_back(C.get()); - for (std::unique_ptr &C : Addresses) - V.push_back(C.get()); for (std::unique_ptr &C : Names) V.push_back(C.get()); for (std::unique_ptr &C : HintNames) @@ -307,11 +303,34 @@ std::vector DelayLoadContents::getChunks(Defined *H) { return V; } +std::vector DelayLoadContents::getDataChunks() { + std::vector V; + for (std::unique_ptr &C : ModuleHandles) + V.push_back(C.get()); + for (std::unique_ptr &C : Addresses) + V.push_back(C.get()); + return V; +} + uint64_t DelayLoadContents::getDirSize() { return Dirs.size() * sizeof(delay_import_directory_table_entry); } -void DelayLoadContents::create() { +// A chunk for the import descriptor table. +class DelayAddressChunk : public Chunk { +public: + explicit DelayAddressChunk(Chunk *C) : Thunk(C) {} + size_t getSize() const override { return 8; } + + void writeTo(uint8_t *Buf) override { + write64le(Buf + FileOff, Thunk->getRVA() + Config->ImageBase); + } + + Chunk *Thunk; +}; + +void DelayLoadContents::create(Defined *H) { + Helper = H; std::map> Map = binImports(Imports); @@ -320,11 +339,15 @@ void DelayLoadContents::create() { StringRef Name = P.first; std::vector &Syms = P.second; + // Create the delay import table header. + if (!DLLNames.count(Name)) + DLLNames[Name] = make_unique(Name); + auto Dir = make_unique(DLLNames[Name].get()); + size_t Base = Addresses.size(); for (DefinedImportData *S : Syms) { - auto T = make_unique(S, Helper); - auto A = make_unique(T.get()); - T->Desc = A.get(); + auto T = make_unique(S, Dir.get(), Helper); + auto A = make_unique(T.get()); Addresses.push_back(std::move(A)); Thunks.push_back(std::move(T)); auto C = @@ -333,8 +356,8 @@ void DelayLoadContents::create() { HintNames.push_back(std::move(C)); } // Terminate with null values. - Addresses.push_back(make_unique(LookupChunkSize)); - Names.push_back(make_unique(LookupChunkSize)); + Addresses.push_back(make_unique(8)); + Names.push_back(make_unique(8)); for (int I = 0, E = Syms.size(); I < E; ++I) Syms[I]->setLocation(Addresses[Base + I].get()); @@ -342,10 +365,7 @@ void DelayLoadContents::create() { MH->setAlign(8); ModuleHandles.push_back(std::unique_ptr(MH)); - // Create the delay import table header. - if (!DLLNames.count(Name)) - DLLNames[Name] = make_unique(Name); - auto Dir = make_unique(DLLNames[Name].get()); + // Fill the delay import table header fields. Dir->ModuleHandle = MH; Dir->AddressTab = Addresses[Base].get(); Dir->NameTab = Names[Base].get(); diff --git a/lld/COFF/DLL.h b/lld/COFF/DLL.h index ac55366c5a59..f0f596974789 100644 --- a/lld/COFF/DLL.h +++ b/lld/COFF/DLL.h @@ -48,15 +48,15 @@ class DelayLoadContents { public: void add(DefinedImportData *Sym) { Imports.push_back(Sym); } bool empty() { return Imports.empty(); } - std::vector getChunks(Defined *Helper); - std::vector> &getDataChunks() { return ModuleHandles; } + void create(Defined *Helper); + std::vector getChunks(); + std::vector getDataChunks(); std::vector> &getCodeChunks() { return Thunks; } uint64_t getDirRVA() { return Dirs[0]->getRVA(); } uint64_t getDirSize(); private: - void create(); Defined *Helper; std::vector Imports; std::vector> Dirs; diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index fb8005b25607..81a9b2425527 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -203,15 +203,16 @@ void Writer::createImportTables() { Sec->addChunk(C); } if (!DelayIdata.empty()) { + DelayIdata.create(Symtab->find("__delayLoadHelper2")); OutputSection *Sec = createSection(".didat"); - for (Chunk *C : DelayIdata.getChunks(Symtab->find("__delayLoadHelper2"))) + for (Chunk *C : DelayIdata.getChunks()) + Sec->addChunk(C); + Sec = createSection(".data"); + for (Chunk *C : DelayIdata.getDataChunks()) Sec->addChunk(C); Sec = createSection(".text"); for (std::unique_ptr &C : DelayIdata.getCodeChunks()) Sec->addChunk(C.get()); - Sec = createSection(".data"); - for (std::unique_ptr &C : DelayIdata.getDataChunks()) - Sec->addChunk(C.get()); } } -- cgit v1.2.3