diff options
-rw-r--r-- | COFF/DLL.cpp | 15 | ||||
-rw-r--r-- | COFF/DLL.h | 1 | ||||
-rw-r--r-- | COFF/Driver.cpp | 3 | ||||
-rw-r--r-- | COFF/PDB.cpp | 3 | ||||
-rw-r--r-- | ELF/LinkerScript.cpp | 7 | ||||
-rw-r--r-- | ELF/OutputSections.cpp | 1 | ||||
-rw-r--r-- | ELF/OutputSections.h | 4 | ||||
-rw-r--r-- | ELF/Writer.cpp | 32 | ||||
-rw-r--r-- | test/COFF/armnt-imports.test | 2 | ||||
-rw-r--r-- | test/COFF/def-export-stdcall.s | 25 | ||||
-rw-r--r-- | test/COFF/hello32.test | 4 | ||||
-rw-r--r-- | test/COFF/imports.test | 8 | ||||
-rw-r--r-- | test/ELF/emit-relocs.s | 13 |
13 files changed, 78 insertions, 40 deletions
diff --git a/COFF/DLL.cpp b/COFF/DLL.cpp index 3ac14e4ea2b0..d76410b67471 100644 --- a/COFF/DLL.cpp +++ b/COFF/DLL.cpp @@ -100,17 +100,13 @@ 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; }; @@ -392,6 +388,7 @@ std::vector<Chunk *> IdataContents::getChunks() { // Add each type in the correct order. std::vector<Chunk *> V; V.insert(V.end(), Dirs.begin(), Dirs.end()); + V.insert(V.end(), Lookups.begin(), Lookups.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()); @@ -407,18 +404,21 @@ void IdataContents::create() { // 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 = Addresses.size(); + size_t Base = Lookups.size(); for (DefinedImportData *S : Syms) { uint16_t Ord = S->getOrdinal(); if (S->getExternalName().empty()) { + Lookups.push_back(make<OrdinalOnlyChunk>(Ord)); Addresses.push_back(make<OrdinalOnlyChunk>(Ord)); continue; } auto *C = make<HintNameChunk>(S->getExternalName(), Ord); + Lookups.push_back(make<LookupChunk>(C)); Addresses.push_back(make<LookupChunk>(C)); Hints.push_back(C); } // Terminate with null values. + Lookups.push_back(make<NullChunk>(ptrSize())); Addresses.push_back(make<NullChunk>(ptrSize())); for (int I = 0, E = Syms.size(); I < E; ++I) @@ -427,6 +427,7 @@ void IdataContents::create() { // Create the import table header. DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName())); auto *Dir = make<ImportDirectoryChunk>(DLLNames.back()); + Dir->LookupTab = Lookups[Base]; Dir->AddressTab = Addresses[Base]; Dirs.push_back(Dir); } diff --git a/COFF/DLL.h b/COFF/DLL.h index 939771b3290c..ad312789edf1 100644 --- a/COFF/DLL.h +++ b/COFF/DLL.h @@ -36,6 +36,7 @@ private: std::vector<DefinedImportData *> Imports; std::vector<Chunk *> Dirs; + std::vector<Chunk *> Lookups; std::vector<Chunk *> Addresses; std::vector<Chunk *> Hints; std::vector<Chunk *> DLLNames; diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp index d871f942737d..96c328b30518 100644 --- a/COFF/Driver.cpp +++ b/COFF/Driver.cpp @@ -434,7 +434,8 @@ std::vector<COFFShortExport> createCOFFShortExportFromConfig() { std::vector<COFFShortExport> Exports; for (Export &E1 : Config->Exports) { COFFShortExport E2; - E2.Name = E1.Name; + // Use SymbolName, which will have any stdcall or fastcall qualifiers. + E2.Name = E1.SymbolName; E2.ExtName = E1.ExtName; E2.Ordinal = E1.Ordinal; E2.Noname = E1.Noname; diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp index a3b3ab7bbab0..eb8c3820412d 100644 --- a/COFF/PDB.cpp +++ b/COFF/PDB.cpp @@ -157,7 +157,8 @@ static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) { fatal(EC, "StreamReader.readArray<CVSymbolArray> failed"); TypeDatabase TDB(0); - CVSymbolDumper SymbolDumper(W, TDB, nullptr, false); + CVSymbolDumper SymbolDumper(W, TDB, CodeViewContainer::ObjectFile, nullptr, + false); if (auto EC = SymbolDumper.dump(Symbols)) fatal(EC, "CVSymbolDumper::dump failed"); } diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp index 75df2cd4bd5c..1ced3e8e8d71 100644 --- a/ELF/LinkerScript.cpp +++ b/ELF/LinkerScript.cpp @@ -463,12 +463,7 @@ void LinkerScript::fabricateDefaultCommands() { // Prefer user supplied address over additional alignment constraint auto I = Config->SectionStartMap.find(Sec->Name); if (I != Config->SectionStartMap.end()) - Commands.push_back( - make<SymbolAssignment>(".", [=] { return I->second; }, "")); - else if (Sec->PageAlign) - OSCmd->AddrExpr = [=] { - return alignTo(Script->getDot(), Config->MaxPageSize); - }; + OSCmd->AddrExpr = [=] { return I->second; }; Commands.push_back(OSCmd); if (Sec->Sections.size()) { diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp index 4f8906a32081..8357d6b03bb1 100644 --- a/ELF/OutputSections.cpp +++ b/ELF/OutputSections.cpp @@ -128,6 +128,7 @@ template <class ELFT> void OutputSection::finalize() { // the section to which the relocation applies. InputSectionBase *S = First->getRelocatedSection(); Info = S->getOutputSection()->SectionIndex; + Flags |= SHF_INFO_LINK; } static uint64_t updateOffset(uint64_t Off, InputSection *S) { diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h index 326348cd5a20..0f2fe68ca708 100644 --- a/ELF/OutputSections.h +++ b/ELF/OutputSections.h @@ -59,10 +59,6 @@ public: Alignment = Val; } - // If true, this section will be page aligned on disk. - // Typically the first section of each PT_LOAD segment has this flag. - bool PageAlign = false; - // Pointer to the first section in PT_LOAD segment, which this section // also resides in. This field is used to correctly compute file offset // of a section. When two sections share the same load segment, difference diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index 258d5e26ef7f..f68e07fc69d7 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -257,19 +257,20 @@ template <class ELFT> void Writer<ELFT>::run() { if (ErrorCount) return; - if (!Script->Opt.HasSections) { - if (!Config->Relocatable) - fixSectionAlignments(); + if (!Script->Opt.HasSections) Script->fabricateDefaultCommands(); - } else { + else Script->synchronize(); - } for (BaseCommand *Base : Script->Opt.Commands) if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) OutputSectionCommands.push_back(Cmd); clearOutputSections(); + + if (!Script->Opt.HasSections &&!Config->Relocatable) + fixSectionAlignments(); + // If -compressed-debug-sections is specified, we need to compress // .debug_* sections. Do it right now because it changes the size of // output sections. @@ -1504,24 +1505,33 @@ void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) { // first section after PT_GNU_RELRO have to be page aligned so that the dynamic // linker can set the permissions. template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { + auto PageAlign = [](OutputSection *Sec) { + OutputSectionCommand *Cmd = Script->getCmd(Sec); + if (Cmd && !Cmd->AddrExpr) + Cmd->AddrExpr = [=] { + return alignTo(Script->getDot(), Config->MaxPageSize); + }; + }; + for (const PhdrEntry &P : Phdrs) if (P.p_type == PT_LOAD && P.First) - P.First->PageAlign = true; + PageAlign(P.First); for (const PhdrEntry &P : Phdrs) { if (P.p_type != PT_GNU_RELRO) continue; if (P.First) - P.First->PageAlign = true; + PageAlign(P.First); // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we // have to align it to a page. - auto End = OutputSections.end(); - auto I = std::find(OutputSections.begin(), End, P.Last); + auto End = OutputSectionCommands.end(); + auto I = + std::find(OutputSectionCommands.begin(), End, Script->getCmd(P.Last)); if (I == End || (I + 1) == End) continue; - OutputSection *Sec = *(I + 1); + OutputSection *Sec = (*(I + 1))->Sec; if (needsPtLoad(Sec)) - Sec->PageAlign = true; + PageAlign(Sec); } } diff --git a/test/COFF/armnt-imports.test b/test/COFF/armnt-imports.test index f0aaebd3f293..519886eb0c06 100644 --- a/test/COFF/armnt-imports.test +++ b/test/COFF/armnt-imports.test @@ -6,7 +6,7 @@ # CHECK: Import { # CHECK: Name: library.dll # CHECK: ImportLookupTableRVA: 0x2028 -# CHECK: ImportAddressTableRVA: 0x2028 +# CHECK: ImportAddressTableRVA: 0x2030 # CHECK: Symbol: function (0) # CHECK: } diff --git a/test/COFF/def-export-stdcall.s b/test/COFF/def-export-stdcall.s new file mode 100644 index 000000000000..cdca7ae76acf --- /dev/null +++ b/test/COFF/def-export-stdcall.s @@ -0,0 +1,25 @@ +# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o %t.obj +# RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall" > %t.def +# RUN: lld-link -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib +# RUN: llvm-nm %t.lib | FileCheck %s +# CHECK: __imp__stdcall@8 +# CHECK: _stdcall@8 + + .def _stdcall@8; + .scl 2; + .type 32; + .endef + .globl _stdcall@8 +_stdcall@8: + movl 8(%esp), %eax + addl 4(%esp), %eax + retl $8 + + .def _dllmain; + .scl 2; + .type 32; + .endef + .globl _dllmain +_dllmain: + retl + diff --git a/test/COFF/hello32.test b/test/COFF/hello32.test index b7c5f28c3534..66b52378aaa3 100644 --- a/test/COFF/hello32.test +++ b/test/COFF/hello32.test @@ -78,7 +78,7 @@ HEADER-NEXT: LoadConfigTableRVA: 0x0 HEADER-NEXT: LoadConfigTableSize: 0x0 HEADER-NEXT: BoundImportRVA: 0x0 HEADER-NEXT: BoundImportSize: 0x0 -HEADER-NEXT: IATRVA: 0x3028 +HEADER-NEXT: IATRVA: 0x3034 HEADER-NEXT: IATSize: 0xC HEADER-NEXT: DelayImportDescriptorRVA: 0x0 HEADER-NEXT: DelayImportDescriptorSize: 0x0 @@ -114,7 +114,7 @@ IMPORTS: AddressSize: 32bit IMPORTS: Import { IMPORTS: Name: std32.dll IMPORTS: ImportLookupTableRVA: 0x3028 -IMPORTS: ImportAddressTableRVA: 0x3028 +IMPORTS: ImportAddressTableRVA: 0x3034 IMPORTS: Symbol: ExitProcess (0) IMPORTS: Symbol: MessageBoxA (1) IMPORTS: } diff --git a/test/COFF/imports.test b/test/COFF/imports.test index 4df6d492ff28..584c24eb1b76 100644 --- a/test/COFF/imports.test +++ b/test/COFF/imports.test @@ -21,14 +21,14 @@ TEXT-NEXT: callq 60 TEXT-NEXT: movl $0, %ecx TEXT-NEXT: callq 18 TEXT-NEXT: callq 29 -TEXT: jmpq *4066(%rip) -TEXT: jmpq *4058(%rip) -TEXT: jmpq *4050(%rip) +TEXT: jmpq *4098(%rip) +TEXT: jmpq *4090(%rip) +TEXT: jmpq *4082(%rip) IMPORT: Import { IMPORT-NEXT: Name: std64.dll IMPORT-NEXT: ImportLookupTableRVA: 0x3028 -IMPORT-NEXT: ImportAddressTableRVA: 0x3028 +IMPORT-NEXT: ImportAddressTableRVA: 0x3048 IMPORT-NEXT: Symbol: ExitProcess (0) IMPORT-NEXT: Symbol: (50) IMPORT-NEXT: Symbol: MessageBoxA (1) diff --git a/test/ELF/emit-relocs.s b/test/ELF/emit-relocs.s index dfe20589e97b..fd9722f13ab0 100644 --- a/test/ELF/emit-relocs.s +++ b/test/ELF/emit-relocs.s @@ -1,16 +1,23 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o # RUN: ld.lld --emit-relocs %t1.o -o %t -# RUN: llvm-readobj -t -r %t | FileCheck %s +# RUN: llvm-readobj -t -r -s %t | FileCheck %s ## Check single dash form. # RUN: ld.lld -emit-relocs %t1.o -o %t1 -# RUN: llvm-readobj -t -r %t1 | FileCheck %s +# RUN: llvm-readobj -t -r -s %t1 | FileCheck %s ## Check alias. # RUN: ld.lld -q %t1.o -o %t2 -# RUN: llvm-readobj -t -r %t2 | FileCheck %s +# RUN: llvm-readobj -t -r -s %t2 | FileCheck %s +# CHECK: Section { +# CHECK: Index: 2 +# CHECK-NEXT: Name: .rela.text +# CHECK-NEXT: Type: SHT_RELA +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_INFO_LINK +# CHECK-NEXT: ] # CHECK: Relocations [ # CHECK-NEXT: Section ({{.*}}) .rela.text { # CHECK-NEXT: 0x201002 R_X86_64_32 .text 0x1 |