[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