Vendor import of lld trunk r304659:
https://llvm.org/svn/llvm-project/lld/trunk@304659
This commit is contained in:
parent
80350c116f
commit
b9a1baec33
15
COFF/DLL.cpp
15
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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
# CHECK: Import {
|
||||
# CHECK: Name: library.dll
|
||||
# CHECK: ImportLookupTableRVA: 0x2028
|
||||
# CHECK: ImportAddressTableRVA: 0x2028
|
||||
# CHECK: ImportAddressTableRVA: 0x2030
|
||||
# CHECK: Symbol: function (0)
|
||||
# CHECK: }
|
||||
|
||||
|
25
test/COFF/def-export-stdcall.s
Normal file
25
test/COFF/def-export-stdcall.s
Normal 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
|
||||
|
@ -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: }
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user