[prev in list] [next in list] [prev in thread] [next in thread]
List: llvm-commits
Subject: Re: [PATCH] [PECOFF] Handle .drectve section.
From: Rui Ueyama <ruiu () google ! com>
Date: 2013-07-31 21:28:47
Message-ID: ec9069419f90f138862e612b581e4151 () llvm-reviews ! chandlerc ! com
[Download RAW message or body]
- updated as per rnk's comments.
Hi kledzik,
http://llvm-reviews.chandlerc.com/D1246
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D1246?vs=3101&id=3117#toc
Files:
lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
test/pecoff/Inputs/drectve.obj.yaml
test/pecoff/drectve.test
["D1246.2.patch" (text/x-patch)]
Index: lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
===================================================================
--- lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -13,12 +13,14 @@
#include "ReaderImportHeader.h"
#include "lld/Core/File.h"
+#include "lld/Driver/Driver.h"
#include "lld/ReaderWriter/Reader.h"
#include "lld/ReaderWriter/ReaderArchive.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Memory.h"
@@ -80,7 +82,11 @@
if ((ec = createDefinedSymbols(symbols, _definedAtoms._atoms)))
return;
- ec = addRelocationReferenceToAtoms();
+ if ((ec = addRelocationReferenceToAtoms()))
+ return;
+
+ // Read .drectve section if exists.
+ ec = maybeReadLinkerDirectives();
}
virtual const atom_collection<DefinedAtom> &defined() const {
@@ -101,6 +107,8 @@
virtual const TargetInfo &getTargetInfo() const { return _targetInfo; }
+ StringRef getLinkerDirectives() const { return _directives; }
+
private:
/// Iterate over the symbol table to retrieve all symbols.
error_code readSymbolTable(vector<const coff_symbol *> &result) {
@@ -376,12 +384,69 @@
return error_code::success();
}
+ /// Find a section by name.
+ error_code findSection(StringRef name, const coff_section *&result) {
+ error_code ec;
+ for (auto si = _obj->begin_sections(), se = _obj->end_sections(); si != se;
+ si.increment(ec)) {
+ const coff_section *section = _obj->getCOFFSection(si);
+ StringRef sectionName;
+ if ((ec = _obj->getSectionName(section, sectionName)))
+ return ec;
+ if (sectionName == name) {
+ result = section;
+ return error_code::success();
+ }
+ }
+ // Section was not found, but it's not an error. This method returns an error
+ // only when there's a read error.
+ return error_code::success();
+ }
+
+ // Convert ArrayRef<uint8_t> to std::string. The array contains a string which
+ // may not be terminated by NUL.
+ std::string ArrayRefToString(ArrayRef<uint8_t> array) {
+ // Skip the UTF-8 byte marker if exists. The contents of .drectve section
+ // is, according to the Microsoft PE/COFF spec, encoded as ANSI or UTF-8
+ // with the BOM marker.
+ //
+ // FIXME: I think "ANSI" in the spec means Windows-1252 encoding, which is a
+ // superset of ASCII. We need to convert it to UTF-8.
+ if (array.size() >= 3 && array[0] == 0xEF && array[1] == 0xBB &&
+ array[2] == 0xBF) {
+ array = array.slice(3);
+ }
+
+ size_t len = 0;
+ size_t e = array.size();
+ while (len < e && array[len] != '\0')
+ ++len;
+ return std::string(reinterpret_cast<const char *>(&array[0]), len);
+ }
+
+ // Read .drectve section contents if exists, and store it to _directives.
+ error_code maybeReadLinkerDirectives() {
+ const coff_section *section = nullptr;
+ if (error_code ec = findSection(".drectve", section))
+ return ec;
+ if (section != nullptr) {
+ ArrayRef<uint8_t> contents;
+ if (error_code ec = _obj->getSectionContents(section, contents))
+ return ec;
+ _directives = std::move(ArrayRefToString(contents));
+ }
+ return error_code::success();
+ }
+
std::unique_ptr<const llvm::object::COFFObjectFile> _obj;
atom_collection_vector<DefinedAtom> _definedAtoms;
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+ // The contents of .drectve section.
+ std::string _directives;
+
// A map from symbol to its name. All symbols should be in this map except
// unnamed ones.
std::map<const coff_symbol *, StringRef> _symbolName;
@@ -396,6 +461,19 @@
const TargetInfo &_targetInfo;
};
+class BumpPtrStringSaver : public llvm::cl::StringSaver {
+public:
+ virtual const char *SaveString(const char *str) {
+ size_t len = strlen(str);
+ char *copy = _alloc.Allocate<char>(len + 1);
+ memcpy(copy, str, len + 1);
+ return copy;
+ }
+
+private:
+ llvm::BumpPtrAllocator _alloc;
+};
+
class ReaderCOFF : public Reader {
public:
explicit ReaderCOFF(const TargetInfo &ti)
@@ -413,10 +491,54 @@
}
private:
+ // Interpret the contents of .drectve section. If exists, the section contains
+ // a string containing command line options. The linker is expected to
+ // interpret the options as if they were given via the command line.
+ //
+ // The section mainly contains /defaultlib (-l in Unix), but can contain any
+ // options as long as they are valid.
+ void handleDirectiveSection(StringRef directives) const {
+ DEBUG({
+ llvm::dbgs() << ".drectve: " << directives << "\n";
+ });
+
+ // Remove const from _targetInfo.
+ // FIXME: Rename TargetInfo -> LinkingContext and treat it a mutable object
+ // in the core linker.
+ PECOFFTargetInfo *targetInfo = (PECOFFTargetInfo *)&_targetInfo;
+
+ // Split the string into tokens, as the shell would do for argv.
+ SmallVector<const char *, 16> tokens;
+ tokens.push_back("link"); // argv[0] is the command name. Will be ignored.
+ llvm::cl::TokenizeWindowsCommandLine(directives, _stringSaver, tokens);
+ tokens.push_back(nullptr);
+
+ // Calls the command line parser to interpret the token string as if they
+ // were given via the command line.
+ int argc = tokens.size() - 1;
+ const char **argv = &tokens[0];
+ std::string errorMessage;
+ llvm::raw_string_ostream stream(errorMessage);
+ bool parseFailed = WinLinkDriver::parse(argc, argv, *targetInfo, stream);
+ stream.flush();
+
+ // Print error message if error.
+ if (parseFailed) {
+ auto msg = Twine("Failed to parse '") + directives + "': "
+ + errorMessage + "\n";
+ llvm::report_fatal_error(msg);
+ }
+ if (!errorMessage.empty()) {
+ llvm::errs() << "lld warning: " << errorMessage << "\n";
+ }
+ }
+
error_code parseCOFFFile(std::unique_ptr<MemoryBuffer> &mb,
std::vector<std::unique_ptr<File> > &result) const {
+ // Parse the memory buffer as PECOFF file.
error_code ec;
- std::unique_ptr<File> file(new FileCOFF(_targetInfo, std::move(mb), ec));
+ std::unique_ptr<FileCOFF> file(
+ new FileCOFF(_targetInfo, std::move(mb), ec));
if (ec)
return ec;
@@ -430,11 +552,17 @@
}
});
+ // Interpret .drectve section if the section has contents.
+ StringRef directives = file->getLinkerDirectives();
+ if (!directives.empty())
+ handleDirectiveSection(directives);
+
result.push_back(std::move(file));
return error_code::success();
}
ReaderArchive _readerArchive;
+ mutable BumpPtrStringSaver _stringSaver;
};
} // end namespace anonymous
Index: test/pecoff/Inputs/drectve.obj.yaml
===================================================================
--- /dev/null
+++ test/pecoff/Inputs/drectve.obj.yaml
@@ -0,0 +1,49 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: ""
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 2147483648
+ SectionData: 2f73756273797374656d3a636f6e736f6c652c34322e31393500
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ NumberOfAuxSymbols: 1
+ AuxiliaryData: 060000000000000000000000000000000000
+ - Name: .data
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ NumberOfAuxSymbols: 1
+ AuxiliaryData: 000000000000000000000000000000000000
+ - Name: _start
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: .drectve
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ NumberOfAuxSymbols: 1
+ AuxiliaryData: 0D0000000000000000000000000000000000
+...
Index: test/pecoff/drectve.test
===================================================================
--- /dev/null
+++ test/pecoff/drectve.test
@@ -0,0 +1,11 @@
+# Test if the linker can properly parse the .drectve section contents.
+# "drectve.obj" contains "/subsystem:console,42.195" in its .drectve
+# section.
+
+# RUN: yaml2obj %p/Inputs/drectve.obj.yaml > %t.obj
+#
+# RUN: lld -flavor link /out:%t1 /entry:start -- %t.obj \
+# RUN: && llvm-readobj -file-headers %t1 | FileCheck %s
+
+CHECK: MajorOperatingSystemVersion: 42
+CHECK: MinorOperatingSystemVersion: 195
_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic