[lld] r241396 - COFF: Implement /merge option.
Rui Ueyama
ruiu at google.com
Sat Jul 4 16:37:32 PDT 2015
Author: ruiu
Date: Sat Jul 4 18:37:32 2015
New Revision: 241396
URL: http://llvm.org/viewvc/llvm-project?rev=241396&view=rev
Log:
COFF: Implement /merge option.
/merge:.foo=.bar makes the linker to merge section .foo with section .bar.
Added:
lld/trunk/test/COFF/merge.test
Modified:
lld/trunk/COFF/Config.h
lld/trunk/COFF/Driver.cpp
lld/trunk/COFF/Driver.h
lld/trunk/COFF/DriverUtils.cpp
lld/trunk/COFF/Writer.cpp
Modified: lld/trunk/COFF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.h?rev=241396&r1=241395&r2=241396&view=diff
==============================================================================
--- lld/trunk/COFF/Config.h (original)
+++ lld/trunk/COFF/Config.h Sat Jul 4 18:37:32 2015
@@ -54,6 +54,7 @@ struct Configuration {
bool DoGC = true;
bool Relocatable = true;
bool Force = false;
+ bool Debug = false;
// Symbols in this set are considered as live by the garbage collector.
std::set<Undefined *> GCRoot;
@@ -70,6 +71,9 @@ struct Configuration {
// Used for /opt:icf
bool ICF = false;
+ // Used for /merge:from=to (e.g. /merge:.rdata=.text)
+ std::map<StringRef, StringRef> Merge;
+
// Options for manifest files.
ManifestKind Manifest = SideBySide;
int ManifestID = 1;
Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=241396&r1=241395&r2=241396&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Sat Jul 4 18:37:32 2015
@@ -121,7 +121,8 @@ LinkerDriver::parseDirectives(StringRef
addUndefined(Arg->getValue());
break;
case OPT_merge:
- // Ignore /merge for now.
+ if (auto EC = parseMerge(Arg->getValue()))
+ return EC;
break;
case OPT_nodefaultlib:
Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));
@@ -290,6 +291,10 @@ bool LinkerDriver::link(llvm::ArrayRef<c
if (auto *Arg = Args.getLastArg(OPT_entry))
Config->Entry = addUndefined(Arg->getValue());
+ // Handle /debug
+ if (Args.hasArg(OPT_debug))
+ Config->Debug = true;
+
// Handle /noentry
if (Args.hasArg(OPT_noentry)) {
if (!Args.hasArg(OPT_dll)) {
@@ -442,6 +447,11 @@ bool LinkerDriver::link(llvm::ArrayRef<c
return false;
}
+ // Handle /merge
+ for (auto *Arg : Args.filtered(OPT_merge))
+ if (parseMerge(Arg->getValue()))
+ return false;
+
// Handle /manifest
if (auto *Arg = Args.getLastArg(OPT_manifest_colon)) {
if (auto EC = parseManifest(Arg->getValue())) {
Modified: lld/trunk/COFF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=241396&r1=241395&r2=241396&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.h (original)
+++ lld/trunk/COFF/Driver.h Sat Jul 4 18:37:32 2015
@@ -132,6 +132,7 @@ std::error_code parseSubsystem(StringRef
uint32_t *Major, uint32_t *Minor);
std::error_code parseAlternateName(StringRef);
+std::error_code parseMerge(StringRef);
// Parses a string in the form of "EMBED[,=<integer>]|NO".
std::error_code parseManifest(StringRef Arg);
Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=241396&r1=241395&r2=241396&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Sat Jul 4 18:37:32 2015
@@ -172,6 +172,23 @@ std::error_code parseAlternateName(Strin
return std::error_code();
}
+// Parse a string of the form of "<from>=<to>".
+// Results are directly written to Config.
+std::error_code parseMerge(StringRef S) {
+ StringRef From, To;
+ std::tie(From, To) = S.split('=');
+ if (From.empty() || To.empty()) {
+ llvm::errs() << "/merge: invalid argument: " << S << "\n";
+ return make_error_code(LLDError::InvalidOption);
+ }
+ auto Pair = Config->Merge.insert(std::make_pair(From, To));
+ bool Inserted = Pair.second;
+ if (!Inserted)
+ llvm::errs() << "warning: " << S << ": already merged into "
+ << Pair.first->second << "\n";
+ return std::error_code();
+}
+
// Parses a string in the form of "EMBED[,=<integer>]|NO".
// Results are directly written to Config.
std::error_code parseManifest(StringRef Arg) {
Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=241396&r1=241395&r2=241396&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Sat Jul 4 18:37:32 2015
@@ -158,6 +158,16 @@ void Writer::dedupCOMDATs() {
doICF(Symtab->getChunks());
}
+static StringRef getOutputSection(StringRef Name) {
+ StringRef S = Name.split('$').first;
+ if (Config->Debug)
+ return S;
+ auto It = Config->Merge.find(S);
+ if (It == Config->Merge.end())
+ return S;
+ return It->second;
+}
+
// Create output section objects and add them to OutputSections.
void Writer::createSections() {
// First, bin chunks by name.
@@ -178,18 +188,16 @@ void Writer::createSections() {
// '$' and all following characters in input section names are
// discarded when determining output section. So, .text$foo
// contributes to .text, for example. See PE/COFF spec 3.2.
- StringRef Name = Map.begin()->first.split('$').first;
- auto Sec = new (CAlloc.Allocate()) OutputSection(Name, 0);
- OutputSections.push_back(Sec);
- for (auto &P : Map) {
- StringRef SectionName = P.first;
- StringRef Base = SectionName.split('$').first;
- if (Base != Sec->getName()) {
+ std::map<StringRef, OutputSection *> Sections;
+ for (auto Pair : Map) {
+ StringRef Name = getOutputSection(Pair.first);
+ OutputSection *&Sec = Sections[Name];
+ if (!Sec) {
size_t SectIdx = OutputSections.size();
- Sec = new (CAlloc.Allocate()) OutputSection(Base, SectIdx);
+ Sec = new (CAlloc.Allocate()) OutputSection(Name, SectIdx);
OutputSections.push_back(Sec);
}
- std::vector<Chunk *> &Chunks = P.second;
+ std::vector<Chunk *> &Chunks = Pair.second;
for (Chunk *C : Chunks) {
Sec->addChunk(C);
Sec->addPermissions(C->getPermissions());
Added: lld/trunk/test/COFF/merge.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/merge.test?rev=241396&view=auto
==============================================================================
--- lld/trunk/test/COFF/merge.test (added)
+++ lld/trunk/test/COFF/merge.test Sat Jul 4 18:37:32 2015
@@ -0,0 +1,53 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld -flavor link2 /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: /merge:.foo=.abc /merge:.bar=.def %t.obj
+# RUN: llvm-readobj -sections %t.exe | FileCheck %s
+
+# CHECK: Name: .def
+# CHECK: Name: .abc
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .foo
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: 000000000000
+ - Name: .bar
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: 000000000000
+symbols:
+ - Name: .foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 6
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .bar
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 6
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
More information about the llvm-commits
mailing list