[lld] r193454 - [PECOFF] Parse /merge command line option.
Rui Ueyama
ruiu at google.com
Fri Oct 25 17:46:57 PDT 2013
Author: ruiu
Date: Fri Oct 25 19:46:57 2013
New Revision: 193454
URL: http://llvm.org/viewvc/llvm-project?rev=193454&view=rev
Log:
[PECOFF] Parse /merge command line option.
/merge:<from>=<to> option makes the linker to combine "from" section to "to"
section. This patch is to parse the option. The actual feature will be
implemented in a subsequent patch.
Modified:
lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
lld/trunk/lib/Driver/WinLinkDriver.cpp
lld/trunk/lib/Driver/WinLinkOptions.td
lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=193454&r1=193453&r2=193454&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Fri Oct 25 19:46:57 2013
@@ -10,6 +10,7 @@
#ifndef LLD_READER_WRITER_PECOFF_LINKER_CONTEXT_H
#define LLD_READER_WRITER_PECOFF_LINKER_CONTEXT_H
+#include <map>
#include <set>
#include <vector>
@@ -184,6 +185,10 @@ public:
void setImageType(ImageType type) { _imageType = type; }
ImageType getImageType() const { return _imageType; }
+ StringRef getFinalSectionName(StringRef sectionName) const;
+ bool addSectionRenaming(raw_ostream &diagnostics,
+ StringRef from, StringRef to);
+
void addNoDefaultLib(StringRef libName) { _noDefaultLibs.insert(libName); }
const std::set<std::string> &getNoDefaultLibs() const {
return _noDefaultLibs;
@@ -255,6 +260,11 @@ private:
std::unique_ptr<Reader> _reader;
std::unique_ptr<Writer> _writer;
+ // A map for section renaming. For example, if there is an entry in the map
+ // whose value is .rdata -> .text, the section contens of .rdata will be
+ // merged to .text in the resulting executable.
+ std::map<std::string, std::string> _renamedSections;
+
// List of files that will be removed on destruction.
std::vector<std::unique_ptr<llvm::FileRemover> > _tempFiles;
};
Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=193454&r1=193453&r2=193454&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Fri Oct 25 19:46:57 2013
@@ -627,6 +627,20 @@ WinLinkDriver::parse(int argc, const cha
break;
}
+ case OPT_merge: {
+ // Parse /merge:<from>=<to>.
+ StringRef from, to;
+ llvm::tie(from, to) = StringRef(inputArg->getValue()).split('=');
+ if (from.empty() || to.empty()) {
+ diagnostics << "error: malformed /merge option: "
+ << inputArg->getValue() << "\n";
+ return false;
+ }
+ if (!ctx.addSectionRenaming(diagnostics, from, to))
+ return false;
+ break;
+ }
+
case OPT_subsystem: {
// Parse /subsystem command line option. The form of /subsystem is
// "subsystem_name[,majorOSVersion[.minorOSVersion]]".
Modified: lld/trunk/lib/Driver/WinLinkOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkOptions.td?rev=193454&r1=193453&r2=193454&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkOptions.td (original)
+++ lld/trunk/lib/Driver/WinLinkOptions.td Fri Oct 25 19:46:57 2013
@@ -29,6 +29,7 @@ def out : P<"out", "Path to file to
def stack : P<"stack", "Size of the stack">;
def machine : P<"machine", "Specify target platform">;
def version : P<"version", "Specify a version number in the PE header">;
+def merge : P<"merge", "Combine sections">;
def subsystem : P<"subsystem", "Specify subsystem">;
def manifest : F<"manifest">;
Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=193454&r1=193453&r2=193454&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Fri Oct 25 19:46:57 2013
@@ -23,6 +23,7 @@
#include "lld/ReaderWriter/Writer.h"
#include <bitset>
+#include <set>
namespace lld {
@@ -101,6 +102,58 @@ bool PECOFFLinkingContext::createImplici
return true;
}
+/// Returns the section name in the resulting executable.
+///
+/// Sections in object files are usually output to the executable with the same
+/// name, but you can rename by command line option. /merge:from=to makes the
+/// linker to combine "from" section contents to "to" section in the
+/// executable. We have a mapping for the renaming. This method looks up the
+/// table and returns a new section name if renamed.
+StringRef
+PECOFFLinkingContext::getFinalSectionName(StringRef sectionName) const {
+ auto it = _renamedSections.find(sectionName);
+ if (it == _renamedSections.end())
+ return sectionName;
+ return getFinalSectionName(it->second);
+}
+
+/// Adds a mapping to the section renaming table. This method will be used for
+/// /merge command line option.
+bool PECOFFLinkingContext::addSectionRenaming(raw_ostream &diagnostics,
+ StringRef from, StringRef to) {
+ auto it = _renamedSections.find(from);
+ if (it != _renamedSections.end()) {
+ if (it->second == to)
+ // There's already the same mapping.
+ return true;
+ diagnostics << "Section \"" << from << "\" is already mapped to \""
+ << it->second << ", so it cannot be mapped to \"" << to << "\".";
+ return true;
+ }
+
+ // Add a mapping, and check if there's no cycle in the renaming mapping. The
+ // cycle detection algorithm we use here is naive, but that's OK because the
+ // number of mapping is usually less than 10.
+ _renamedSections[from] = to;
+ for (auto elem : _renamedSections) {
+ StringRef sectionName = elem.first;
+ std::set<StringRef> visited;
+ visited.insert(sectionName);
+ for (;;) {
+ auto it = _renamedSections.find(sectionName);
+ if (it == _renamedSections.end())
+ break;
+ if (visited.count(it->second)) {
+ diagnostics << "/merge:" << from << "=" << to << " makes a cycle";
+ return false;
+ }
+ sectionName = it->second;
+ visited.insert(sectionName);
+ }
+ }
+ return true;
+}
+
/// Try to find the input library file from the search paths and append it to
/// the input file list. Returns true if the library file is found.
StringRef PECOFFLinkingContext::searchLibraryFile(StringRef filename) const {
Modified: lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=193454&r1=193453&r2=193454&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Fri Oct 25 19:46:57 2013
@@ -233,6 +233,19 @@ TEST_F(WinLinkParserTest, Include) {
EXPECT_EQ("foo", symbols[0]);
}
+TEST_F(WinLinkParserTest, Merge) {
+ EXPECT_TRUE(parse("link.exe", "/merge:.foo=.bar", "/merge:.bar=.baz",
+ "a.out", nullptr));
+ EXPECT_EQ(".baz", _context.getFinalSectionName(".foo"));
+ EXPECT_EQ(".baz", _context.getFinalSectionName(".bar"));
+ EXPECT_EQ(".abc", _context.getFinalSectionName(".abc"));
+}
+
+TEST_F(WinLinkParserTest, Merge_Circular) {
+ EXPECT_FALSE(parse("link.exe", "/merge:.foo=.bar", "/merge:.bar=.foo",
+ "a.out", nullptr));
+}
+
//
// Tests for /defaultlib and /nodefaultlib.
//
More information about the llvm-commits
mailing list