[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