diff options
Diffstat (limited to 'COFF/DLL.cpp')
-rw-r--r-- | COFF/DLL.cpp | 160 |
1 files changed, 68 insertions, 92 deletions
diff --git a/COFF/DLL.cpp b/COFF/DLL.cpp index f93dc5cde44ca..3ac14e4ea2b0b 100644 --- a/COFF/DLL.cpp +++ b/COFF/DLL.cpp @@ -100,13 +100,17 @@ public: void writeTo(uint8_t *Buf) const override { auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff); - E->ImportLookupTableRVA = LookupTab->getRVA(); E->NameRVA = DLLName->getRVA(); + + // The import descriptor table contains two pointers to + // the tables describing dllimported symbols. But the + // Windows loader actually uses only one. So we create + // only one table and set both fields to its address. + E->ImportLookupTableRVA = AddressTab->getRVA(); E->ImportAddressTableRVA = AddressTab->getRVA(); } Chunk *DLLName; - Chunk *LookupTab; Chunk *AddressTab; }; @@ -136,9 +140,9 @@ binImports(const std::vector<DefinedImportData *> &Imports) { M[Sym->getDLLName().lower()].push_back(Sym); std::vector<std::vector<DefinedImportData *>> V; - for (auto &P : M) { + for (auto &KV : M) { // Sort symbols by name for each group. - std::vector<DefinedImportData *> &Syms = P.second; + std::vector<DefinedImportData *> &Syms = KV.second; std::sort(Syms.begin(), Syms.end(), [](DefinedImportData *A, DefinedImportData *B) { return A->getName() < B->getName(); @@ -383,21 +387,14 @@ uint64_t IdataContents::getIATSize() { // See Microsoft PE/COFF spec 5.4 for details. std::vector<Chunk *> IdataContents::getChunks() { create(); - std::vector<Chunk *> V; + // The loader assumes a specific order of data. // Add each type in the correct order. - for (std::unique_ptr<Chunk> &C : Dirs) - V.push_back(C.get()); - for (std::unique_ptr<Chunk> &C : Lookups) - V.push_back(C.get()); - for (std::unique_ptr<Chunk> &C : Addresses) - V.push_back(C.get()); - for (std::unique_ptr<Chunk> &C : Hints) - V.push_back(C.get()); - for (auto &P : DLLNames) { - std::unique_ptr<Chunk> &C = P.second; - V.push_back(C.get()); - } + std::vector<Chunk *> V; + V.insert(V.end(), Dirs.begin(), Dirs.end()); + V.insert(V.end(), Addresses.begin(), Addresses.end()); + V.insert(V.end(), Hints.begin(), Hints.end()); + V.insert(V.end(), DLLNames.begin(), DLLNames.end()); return V; } @@ -406,65 +403,50 @@ void IdataContents::create() { // Create .idata contents for each DLL. for (std::vector<DefinedImportData *> &Syms : V) { - StringRef Name = Syms[0]->getDLLName(); - // Create lookup and address tables. If they have external names, // we need to create HintName chunks to store the names. // If they don't (if they are import-by-ordinals), we store only // ordinal values to the table. - size_t Base = Lookups.size(); + size_t Base = Addresses.size(); for (DefinedImportData *S : Syms) { uint16_t Ord = S->getOrdinal(); if (S->getExternalName().empty()) { - Lookups.push_back(make_unique<OrdinalOnlyChunk>(Ord)); - Addresses.push_back(make_unique<OrdinalOnlyChunk>(Ord)); + Addresses.push_back(make<OrdinalOnlyChunk>(Ord)); continue; } - auto C = make_unique<HintNameChunk>(S->getExternalName(), Ord); - Lookups.push_back(make_unique<LookupChunk>(C.get())); - Addresses.push_back(make_unique<LookupChunk>(C.get())); - Hints.push_back(std::move(C)); + auto *C = make<HintNameChunk>(S->getExternalName(), Ord); + Addresses.push_back(make<LookupChunk>(C)); + Hints.push_back(C); } // Terminate with null values. - Lookups.push_back(make_unique<NullChunk>(ptrSize())); - Addresses.push_back(make_unique<NullChunk>(ptrSize())); + Addresses.push_back(make<NullChunk>(ptrSize())); for (int I = 0, E = Syms.size(); I < E; ++I) - Syms[I]->setLocation(Addresses[Base + I].get()); + Syms[I]->setLocation(Addresses[Base + I]); // Create the import table header. - if (!DLLNames.count(Name)) - DLLNames[Name] = make_unique<StringChunk>(Name); - auto Dir = make_unique<ImportDirectoryChunk>(DLLNames[Name].get()); - Dir->LookupTab = Lookups[Base].get(); - Dir->AddressTab = Addresses[Base].get(); - Dirs.push_back(std::move(Dir)); + DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName())); + auto *Dir = make<ImportDirectoryChunk>(DLLNames.back()); + Dir->AddressTab = Addresses[Base]; + Dirs.push_back(Dir); } // Add null terminator. - Dirs.push_back(make_unique<NullChunk>(sizeof(ImportDirectoryTableEntry))); + Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry))); } std::vector<Chunk *> DelayLoadContents::getChunks() { std::vector<Chunk *> V; - for (std::unique_ptr<Chunk> &C : Dirs) - V.push_back(C.get()); - for (std::unique_ptr<Chunk> &C : Names) - V.push_back(C.get()); - for (std::unique_ptr<Chunk> &C : HintNames) - V.push_back(C.get()); - for (auto &P : DLLNames) { - std::unique_ptr<Chunk> &C = P.second; - V.push_back(C.get()); - } + V.insert(V.end(), Dirs.begin(), Dirs.end()); + V.insert(V.end(), Names.begin(), Names.end()); + V.insert(V.end(), HintNames.begin(), HintNames.end()); + V.insert(V.end(), DLLNames.begin(), DLLNames.end()); return V; } std::vector<Chunk *> DelayLoadContents::getDataChunks() { std::vector<Chunk *> V; - for (std::unique_ptr<Chunk> &C : ModuleHandles) - V.push_back(C.get()); - for (std::unique_ptr<Chunk> &C : Addresses) - V.push_back(C.get()); + V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end()); + V.insert(V.end(), Addresses.begin(), Addresses.end()); return V; } @@ -478,55 +460,51 @@ void DelayLoadContents::create(Defined *H) { // Create .didat contents for each DLL. for (std::vector<DefinedImportData *> &Syms : V) { - StringRef Name = Syms[0]->getDLLName(); - // Create the delay import table header. - if (!DLLNames.count(Name)) - DLLNames[Name] = make_unique<StringChunk>(Name); - auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get()); + DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName())); + auto *Dir = make<DelayDirectoryChunk>(DLLNames.back()); size_t Base = Addresses.size(); for (DefinedImportData *S : Syms) { - Chunk *T = newThunkChunk(S, Dir.get()); - auto A = make_unique<DelayAddressChunk>(T); - Addresses.push_back(std::move(A)); - Thunks.push_back(std::unique_ptr<Chunk>(T)); + Chunk *T = newThunkChunk(S, Dir); + auto *A = make<DelayAddressChunk>(T); + Addresses.push_back(A); + Thunks.push_back(T); StringRef ExtName = S->getExternalName(); if (ExtName.empty()) { - Names.push_back(make_unique<OrdinalOnlyChunk>(S->getOrdinal())); + Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal())); } else { - auto C = make_unique<HintNameChunk>(ExtName, 0); - Names.push_back(make_unique<LookupChunk>(C.get())); - HintNames.push_back(std::move(C)); + auto *C = make<HintNameChunk>(ExtName, 0); + Names.push_back(make<LookupChunk>(C)); + HintNames.push_back(C); } } // Terminate with null values. - Addresses.push_back(make_unique<NullChunk>(8)); - Names.push_back(make_unique<NullChunk>(8)); + Addresses.push_back(make<NullChunk>(8)); + Names.push_back(make<NullChunk>(8)); for (int I = 0, E = Syms.size(); I < E; ++I) - Syms[I]->setLocation(Addresses[Base + I].get()); - auto *MH = new NullChunk(8); + Syms[I]->setLocation(Addresses[Base + I]); + auto *MH = make<NullChunk>(8); MH->setAlign(8); - ModuleHandles.push_back(std::unique_ptr<Chunk>(MH)); + ModuleHandles.push_back(MH); // Fill the delay import table header fields. Dir->ModuleHandle = MH; - Dir->AddressTab = Addresses[Base].get(); - Dir->NameTab = Names[Base].get(); - Dirs.push_back(std::move(Dir)); + Dir->AddressTab = Addresses[Base]; + Dir->NameTab = Names[Base]; + Dirs.push_back(Dir); } // Add null terminator. - Dirs.push_back( - make_unique<NullChunk>(sizeof(delay_import_directory_table_entry))); + Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry))); } Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) { switch (Config->Machine) { case AMD64: - return new ThunkChunkX64(S, Dir, Helper); + return make<ThunkChunkX64>(S, Dir, Helper); case I386: - return new ThunkChunkX86(S, Dir, Helper); + return make<ThunkChunkX86>(S, Dir, Helper); default: llvm_unreachable("unsupported machine type"); } @@ -537,34 +515,32 @@ EdataContents::EdataContents() { for (Export &E : Config->Exports) MaxOrdinal = std::max(MaxOrdinal, E.Ordinal); - auto *DLLName = new StringChunk(sys::path::filename(Config->OutputFile)); - auto *AddressTab = new AddressTableChunk(MaxOrdinal); + auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile)); + auto *AddressTab = make<AddressTableChunk>(MaxOrdinal); std::vector<Chunk *> Names; for (Export &E : Config->Exports) if (!E.Noname) - Names.push_back(new StringChunk(E.ExportName)); + Names.push_back(make<StringChunk>(E.ExportName)); std::vector<Chunk *> Forwards; for (Export &E : Config->Exports) { if (E.ForwardTo.empty()) continue; - E.ForwardChunk = new StringChunk(E.ForwardTo); + E.ForwardChunk = make<StringChunk>(E.ForwardTo); Forwards.push_back(E.ForwardChunk); } - auto *NameTab = new NamePointersChunk(Names); - auto *OrdinalTab = new ExportOrdinalChunk(Names.size()); - auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName, - AddressTab, NameTab, OrdinalTab); - Chunks.push_back(std::unique_ptr<Chunk>(Dir)); - Chunks.push_back(std::unique_ptr<Chunk>(DLLName)); - Chunks.push_back(std::unique_ptr<Chunk>(AddressTab)); - Chunks.push_back(std::unique_ptr<Chunk>(NameTab)); - Chunks.push_back(std::unique_ptr<Chunk>(OrdinalTab)); - for (Chunk *C : Names) - Chunks.push_back(std::unique_ptr<Chunk>(C)); - for (Chunk *C : Forwards) - Chunks.push_back(std::unique_ptr<Chunk>(C)); + auto *NameTab = make<NamePointersChunk>(Names); + auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size()); + auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName, + AddressTab, NameTab, OrdinalTab); + Chunks.push_back(Dir); + Chunks.push_back(DLLName); + Chunks.push_back(AddressTab); + Chunks.push_back(NameTab); + Chunks.push_back(OrdinalTab); + Chunks.insert(Chunks.end(), Names.begin(), Names.end()); + Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end()); } } // namespace coff |