summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COFF/DLL.cpp15
-rw-r--r--COFF/DLL.h1
-rw-r--r--COFF/Driver.cpp3
-rw-r--r--COFF/PDB.cpp3
-rw-r--r--ELF/LinkerScript.cpp7
-rw-r--r--ELF/OutputSections.cpp1
-rw-r--r--ELF/OutputSections.h4
-rw-r--r--ELF/Writer.cpp32
-rw-r--r--test/COFF/armnt-imports.test2
-rw-r--r--test/COFF/def-export-stdcall.s25
-rw-r--r--test/COFF/hello32.test4
-rw-r--r--test/COFF/imports.test8
-rw-r--r--test/ELF/emit-relocs.s13
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