[lld] r329471 - COFF: Process /merge flag as we create output sections.
Peter Collingbourne via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 6 17:46:55 PDT 2018
Author: pcc
Date: Fri Apr 6 17:46:55 2018
New Revision: 329471
URL: http://llvm.org/viewvc/llvm-project?rev=329471&view=rev
Log:
COFF: Process /merge flag as we create output sections.
With this we can merge builtin sections.
Differential Revision: https://reviews.llvm.org/D45350
Modified:
lld/trunk/COFF/DLL.h
lld/trunk/COFF/DriverUtils.cpp
lld/trunk/COFF/Writer.cpp
lld/trunk/test/COFF/export32.test
lld/trunk/test/COFF/merge.test
lld/trunk/test/COFF/unwind.test
Modified: lld/trunk/COFF/DLL.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.h?rev=329471&r1=329470&r2=329471&view=diff
==============================================================================
--- lld/trunk/COFF/DLL.h (original)
+++ lld/trunk/COFF/DLL.h Fri Apr 6 17:46:55 2018
@@ -76,6 +76,11 @@ class EdataContents {
public:
EdataContents();
std::vector<Chunk *> Chunks;
+
+ uint64_t getRVA() { return Chunks[0]->getRVA(); }
+ uint64_t getSize() {
+ return Chunks.back()->getRVA() + Chunks.back()->getSize() - getRVA();
+ }
};
} // namespace coff
Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=329471&r1=329470&r2=329471&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Fri Apr 6 17:46:55 2018
@@ -185,6 +185,10 @@ void parseMerge(StringRef S) {
std::tie(From, To) = S.split('=');
if (From.empty() || To.empty())
fatal("/merge: invalid argument: " + S);
+ if (From == ".rsrc" || To == ".rsrc")
+ fatal("/merge: cannot merge '.rsrc' with any section");
+ if (From == ".reloc" || To == ".reloc")
+ fatal("/merge: cannot merge '.reloc' with any section");
auto Pair = Config->Merge.insert(std::make_pair(From, To));
bool Inserted = Pair.second;
if (!Inserted) {
Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=329471&r1=329470&r2=329471&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Fri Apr 6 17:46:55 2018
@@ -209,12 +209,23 @@ private:
OutputSection *TextSec;
OutputSection *RdataSec;
OutputSection *DataSec;
- OutputSection *PdataSec;
OutputSection *IdataSec;
OutputSection *EdataSec;
OutputSection *DidatSec;
OutputSection *RsrcSec;
OutputSection *RelocSec;
+
+ // The first and last .pdata sections in the output file.
+ //
+ // We need to keep track of the location of .pdata in whichever section it
+ // gets merged into so that we can sort its contents and emit a correct data
+ // directory entry for the exception table. This is also the case for some
+ // other sections (such as .edata) but because the contents of those sections
+ // are entirely linker-generated we can keep track of their locations using
+ // the chunks that the linker creates. All .pdata chunks come from input
+ // files, so we need to keep track of them separately.
+ Chunk *FirstPdata = nullptr;
+ Chunk *LastPdata;
};
} // anonymous namespace
@@ -362,17 +373,12 @@ void Writer::run() {
fatal("failed to write the output file: " + toString(std::move(E)));
}
-static StringRef getOutputSection(StringRef Name) {
+static StringRef getOutputSectionName(StringRef Name) {
StringRef S = Name.split('$').first;
// Treat a later period as a separator for MinGW, for sections like
// ".ctors.01234".
- S = S.substr(0, S.find('.', 1));
-
- auto It = Config->Merge.find(S);
- if (It == Config->Merge.end())
- return S;
- return It->second;
+ return S.substr(0, S.find('.', 1));
}
// For /order.
@@ -403,10 +409,15 @@ void Writer::createSections() {
SmallDenseMap<StringRef, OutputSection *> Sections;
auto CreateSection = [&](StringRef Name, uint32_t Perms) {
- auto Sec = make<OutputSection>(Name);
+ auto I = Config->Merge.find(Name);
+ if (I != Config->Merge.end())
+ Name = I->second;
+ OutputSection *&Sec = Sections[Name];
+ if (!Sec) {
+ Sec = make<OutputSection>(Name);
+ OutputSections.push_back(Sec);
+ }
Sec->addPermissions(Perms);
- OutputSections.push_back(Sec);
- Sections[Name] = Sec;
return Sec;
};
@@ -415,7 +426,7 @@ void Writer::createSections() {
CreateSection(".bss", BSS | R | W);
RdataSec = CreateSection(".rdata", DATA | R);
DataSec = CreateSection(".data", DATA | R | W);
- PdataSec = CreateSection(".pdata", DATA | R);
+ CreateSection(".pdata", DATA | R);
IdataSec = CreateSection(".idata", DATA | R);
EdataSec = CreateSection(".edata", DATA | R);
DidatSec = CreateSection(".didat", DATA | R);
@@ -444,12 +455,13 @@ void Writer::createSections() {
// discarded when determining output section. So, .text$foo
// contributes to .text, for example. See PE/COFF spec 3.2.
for (auto Pair : Map) {
- StringRef Name = getOutputSection(Pair.first);
- OutputSection *&Sec = Sections[Name];
- if (!Sec) {
- Sec = make<OutputSection>(Name);
- OutputSections.push_back(Sec);
+ StringRef Name = getOutputSectionName(Pair.first);
+ if (Name == ".pdata") {
+ if (!FirstPdata)
+ FirstPdata = Pair.second.front();
+ LastPdata = Pair.second.back();
}
+ OutputSection *Sec = CreateSection(Name, 0);
std::vector<Chunk *> &Chunks = Pair.second;
for (Chunk *C : Chunks) {
Sec->addChunk(C);
@@ -838,9 +850,9 @@ template <typename PEHeaderTy> void Writ
// Write data directory
auto *Dir = reinterpret_cast<data_directory *>(Buf);
Buf += sizeof(*Dir) * NumberfOfDataDirectory;
- if (EdataSec->getVirtualSize()) {
- Dir[EXPORT_TABLE].RelativeVirtualAddress = EdataSec->getRVA();
- Dir[EXPORT_TABLE].Size = EdataSec->getVirtualSize();
+ if (!Config->Exports.empty()) {
+ Dir[EXPORT_TABLE].RelativeVirtualAddress = Edata.getRVA();
+ Dir[EXPORT_TABLE].Size = Edata.getSize();
}
if (!Idata.empty()) {
Dir[IMPORT_TABLE].RelativeVirtualAddress = Idata.getDirRVA();
@@ -852,9 +864,10 @@ template <typename PEHeaderTy> void Writ
Dir[RESOURCE_TABLE].RelativeVirtualAddress = RsrcSec->getRVA();
Dir[RESOURCE_TABLE].Size = RsrcSec->getVirtualSize();
}
- if (PdataSec->getVirtualSize()) {
- Dir[EXCEPTION_TABLE].RelativeVirtualAddress = PdataSec->getRVA();
- Dir[EXCEPTION_TABLE].Size = PdataSec->getVirtualSize();
+ if (FirstPdata) {
+ Dir[EXCEPTION_TABLE].RelativeVirtualAddress = FirstPdata->getRVA();
+ Dir[EXCEPTION_TABLE].Size =
+ LastPdata->getRVA() + LastPdata->getSize() - FirstPdata->getRVA();
}
if (RelocSec->getVirtualSize()) {
Dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = RelocSec->getRVA();
@@ -1159,11 +1172,15 @@ void Writer::writeBuildId() {
// Sort .pdata section contents according to PE/COFF spec 5.5.
void Writer::sortExceptionTable() {
- if (PdataSec->getVirtualSize() == 0)
+ if (!FirstPdata)
return;
// We assume .pdata contains function table entries only.
- uint8_t *Begin = Buffer->getBufferStart() + PdataSec->getFileOff();
- uint8_t *End = Begin + PdataSec->getVirtualSize();
+ auto BufAddr = [&](Chunk *C) {
+ return Buffer->getBufferStart() + C->getOutputSection()->getFileOff() +
+ C->getRVA() - C->getOutputSection()->getRVA();
+ };
+ uint8_t *Begin = BufAddr(FirstPdata);
+ uint8_t *End = BufAddr(LastPdata) + LastPdata->getSize();
if (Config->Machine == AMD64) {
struct Entry { ulittle32_t Begin, End, Unwind; };
sort(parallel::par, (Entry *)Begin, (Entry *)End,
Modified: lld/trunk/test/COFF/export32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/export32.test?rev=329471&r1=329470&r2=329471&view=diff
==============================================================================
--- lld/trunk/test/COFF/export32.test (original)
+++ lld/trunk/test/COFF/export32.test Fri Apr 6 17:46:55 2018
@@ -2,6 +2,10 @@
#
# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2
# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK1 %s
+#
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 /merge:.edata=.rdata
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK1 %s
+# RUN: llvm-readobj -file-headers -sections %t.dll | FileCheck -check-prefix=HEADER-MERGE %s
# CHECK1: Export Table:
# CHECK1: DLL name: export32.test.tmp.dll
@@ -10,6 +14,12 @@
# CHECK1-NEXT: 1 0x1008 exportfn1
# CHECK1-NEXT: 2 0x1010 exportfn2
+# HEADER-MERGE: ExportTableRVA: 0x2000
+# HEADER-MERGE-NEXT: ExportTableSize: 0x7E
+# HEADER-MERGE: Name: .rdata
+# HEADER-MERGE-NEXT: VirtualSize: 0x7E
+# HEADER-MERGE-NEXT: VirtualAddress: 0x2000
+
# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1, at 5 \
# RUN: /export:exportfn2 /export:mangled
# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK2 %s
Modified: lld/trunk/test/COFF/merge.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/merge.test?rev=329471&r1=329470&r2=329471&view=diff
==============================================================================
--- lld/trunk/test/COFF/merge.test (original)
+++ lld/trunk/test/COFF/merge.test Fri Apr 6 17:46:55 2018
@@ -3,9 +3,21 @@
# RUN: /merge:.foo=.abc /merge:.bar=.def %t.obj /debug
# RUN: llvm-readobj -sections %t.exe | FileCheck %s
+# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: /merge:.rsrc=.foo %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-RSRC %s
+# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: /merge:.foo=.rsrc %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-RSRC %s
+# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: /merge:.reloc=.foo %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-RELOC %s
+# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: /merge:.foo=.reloc %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-RELOC %s
+
# CHECK: Name: .def
# CHECK: Name: .abc
+# NO-RSRC: /merge: cannot merge '.rsrc' with any section
+# NO-RELOC: /merge: cannot merge '.reloc' with any section
+
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Modified: lld/trunk/test/COFF/unwind.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/unwind.test?rev=329471&r1=329470&r2=329471&view=diff
==============================================================================
--- lld/trunk/test/COFF/unwind.test (original)
+++ lld/trunk/test/COFF/unwind.test Fri Apr 6 17:46:55 2018
@@ -4,12 +4,24 @@
# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=HEADER %s
# RUN: llvm-objdump -unwind-info %t.exe | FileCheck -check-prefix=UNWIND %s
#
-# HEADER: ExceptionTableRVA: 0x2000
+# RUN: lld-link /merge:.pdata=.rdata /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers -sections %t.exe | FileCheck -check-prefix=HEADER-MERGE %s
+#
+# HEADER: ExceptionTableRVA: 0x3000
+#
+# FIXME: llvm-readobj currently does not understand files with .pdata merged
+# into .rdata. But we can at least check that the section headers look correct.
+#
+# HEADER-MERGE: ExceptionTableRVA: 0x2000
+# HEADER-MERGE-NEXT: ExceptionTableSize: 0x30
+# HEADER-MERGE: Name: .rdata
+# HEADER-MERGE-NEXT: VirtualSize: 0x34
+# HEADER-MERGE-NEXT: VirtualAddress: 0x2000
#
# UNWIND: Function Table:
# UNWIND: Start Address: 0x1000
# UNWIND: End Address: 0x101b
-# UNWIND: Unwind Info Address: 0x3000
+# UNWIND: Unwind Info Address: 0x4000
# UNWIND: Version: 1
# UNWIND: Flags: 1 UNW_ExceptionHandler
# UNWIND: Size of prolog: 18
@@ -26,7 +38,7 @@
# UNWIND: Function Table:
# UNWIND: Start Address: 0x1012
# UNWIND: End Address: 0x1012
-# UNWIND: Unwind Info Address: 0x301c
+# UNWIND: Unwind Info Address: 0x401c
# UNWIND: Version: 1
# UNWIND: Flags: 4 UNW_ChainInfo
# UNWIND: Size of prolog: 0
@@ -35,7 +47,7 @@
# UNWIND: Function Table:
# UNWIND: Start Address: 0x101b
# UNWIND: End Address: 0x101c
-# UNWIND: Unwind Info Address: 0x302c
+# UNWIND: Unwind Info Address: 0x402c
# UNWIND: Version: 1
# UNWIND: Flags: 0
# UNWIND: Size of prolog: 0
@@ -44,7 +56,7 @@
# UNWIND: Function Table:
# UNWIND: Start Address: 0x101c
# UNWIND: End Address: 0x1039
-# UNWIND: Unwind Info Address: 0x3034
+# UNWIND: Unwind Info Address: 0x4034
# UNWIND: Version: 1
# UNWIND: Flags: 0
# UNWIND: Size of prolog: 14
@@ -122,6 +134,10 @@ sections:
- VirtualAddress: 44
SymbolName: .xdata
Type: IMAGE_REL_AMD64_ADDR32NB
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 00000000
symbols:
- Name: .text
Value: 0
More information about the llvm-commits
mailing list