Vendor import of lld trunk r304659:

https://llvm.org/svn/llvm-project/lld/trunk@304659
This commit is contained in:
Dimitry Andric 2017-06-03 15:21:18 +00:00
parent 80350c116f
commit b9a1baec33
13 changed files with 78 additions and 40 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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");
}

View File

@ -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()) {

View File

@ -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) {

View File

@ -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

View File

@ -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);
}
}

View File

@ -6,7 +6,7 @@
# CHECK: Import {
# CHECK: Name: library.dll
# CHECK: ImportLookupTableRVA: 0x2028
# CHECK: ImportAddressTableRVA: 0x2028
# CHECK: ImportAddressTableRVA: 0x2030
# CHECK: Symbol: function (0)
# CHECK: }

View File

@ -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

View File

@ -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: }

View File

@ -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)

View File

@ -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