[PATCH] D29892: ar: add llvm-dlltool support

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Mon May 15 08:22:25 PDT 2017


Martell Malone via Phabricator <reviews at reviews.llvm.org> writes:

> martell updated this revision to Diff 98637.
> martell added a comment.
> Herald added a subscriber: inglorion.
>
> light update to take https://reviews.llvm.org/D32689 into account.
>
> note:
> also seems `llvm-readobj` can't read weak externals
> will have to add support on top of the short import libs support I done previously.
>
>
> Repository:
>   rL LLVM
>
> https://reviews.llvm.org/D29892
>
> Files:
>   include/llvm/DlltoolDriver/DlltoolDriver.h
>   include/llvm/Object/COFFImportFile.h
>   include/llvm/Object/COFFModuleDefinition.h
>   lib/CMakeLists.txt
>   lib/DlltoolDriver/CMakeLists.txt
>   lib/DlltoolDriver/DlltoolDriver.cpp
>   lib/DlltoolDriver/LLVMBuild.txt
>   lib/DlltoolDriver/Options.td
>   lib/Object/ArchiveWriter.cpp
>   lib/Object/COFFImportFile.cpp
>   lib/Object/COFFModuleDefinition.cpp
>   test/DllTool/coff-exports.def
>   test/DllTool/lit.local.cfg
>   tools/llvm-ar/CMakeLists.txt
>   tools/llvm-ar/llvm-ar.cpp
>
> Index: tools/llvm-ar/llvm-ar.cpp
> ===================================================================
> --- tools/llvm-ar/llvm-ar.cpp
> +++ tools/llvm-ar/llvm-ar.cpp
> @@ -16,6 +16,7 @@
>  #include "llvm/ADT/Triple.h"
>  #include "llvm/IR/LLVMContext.h"
>  #include "llvm/IR/Module.h"
> +#include "llvm/DlltoolDriver/DlltoolDriver.h"
>  #include "llvm/LibDriver/LibDriver.h"
>  #include "llvm/Object/Archive.h"
>  #include "llvm/Object/ArchiveWriter.h"
> @@ -859,6 +860,9 @@
>    llvm::InitializeAllAsmParsers();
>  
>    StringRef Stem = sys::path::stem(ToolName);
> +  if (Stem.find("dlltool") != StringRef::npos)
> +    return dlltoolDriverMain(makeArrayRef(argv, argc));
> +
>    if (Stem.find("ranlib") == StringRef::npos &&
>        Stem.find("lib") != StringRef::npos)
>      return libDriverMain(makeArrayRef(argv, argc));
> @@ -874,5 +878,5 @@
>      return ranlib_main();
>    if (Stem.find("ar") != StringRef::npos)
>      return ar_main();
> -  fail("Not ranlib, ar or lib!");
> +  fail("Not ranlib, ar, lib or dlltool!");
>  }
> Index: tools/llvm-ar/CMakeLists.txt
> ===================================================================
> --- tools/llvm-ar/CMakeLists.txt
> +++ tools/llvm-ar/CMakeLists.txt
> @@ -1,6 +1,7 @@
>  set(LLVM_LINK_COMPONENTS
>    ${LLVM_TARGETS_TO_BUILD}
>    Core
> +  DlltoolDriver
>    LibDriver
>    Object
>    Support
> @@ -15,3 +16,4 @@
>  
>  add_llvm_tool_symlink(llvm-ranlib llvm-ar)
>  add_llvm_tool_symlink(llvm-lib llvm-ar)
> +add_llvm_tool_symlink(llvm-dlltool llvm-ar)
> Index: test/DllTool/lit.local.cfg
> ===================================================================
> --- /dev/null
> +++ test/DllTool/lit.local.cfg
> @@ -0,0 +1 @@
> +config.suffixes = ['.def']
> Index: test/DllTool/coff-exports.def
> ===================================================================
> --- /dev/null
> +++ test/DllTool/coff-exports.def
> @@ -0,0 +1,13 @@
> +; RUN: llvm-dlltool -a x86_64 %s %t.a
> +; RUN: llvm-readobj -coff-exports %t.a | FileCheck %s
> +
> +LIBRARY test.dll
> +EXPORTS
> +TestFunction
> +
> +; CHECK: File: test.dll
> +; CHECK: Format: COFF-import-file
> +; CHECK: Type: code
> +; CHECK: Name type: name
> +; CHECK: Symbol: __imp_TestFunction
> +; CHECK: Symbol: TestFunction
> Index: lib/Object/COFFModuleDefinition.cpp
> ===================================================================
> --- lib/Object/COFFModuleDefinition.cpp
> +++ lib/Object/COFFModuleDefinition.cpp
> @@ -55,8 +55,10 @@
>    StringRef Value;
>  };
>  
> -static bool isDecorated(StringRef Sym) {
> -  return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?");
> +static bool isDecorated(StringRef Sym, bool MingwDef) {
> +  // Disable Sym.startswith("_") for mingw-w64
> +  return (!MingwDef && Sym.startswith("_")) ||
> +          Sym.startswith("@") || Sym.startswith("?");
>  }
>  
>  static Error createError(const Twine &Err) {
> @@ -82,6 +84,10 @@
>        return lex();
>      }
>      case '=':
> +      // This lets us handle  "==" which is a dlltool ism
> +      if (Buf[1] == '=')
> +        Buf = Buf.drop_front();
> +
>        Buf = Buf.drop_front();
>        return Token(Equal, "=");
>      case ',':
> @@ -120,7 +126,8 @@
>  
>  class Parser {
>  public:
> -  explicit Parser(StringRef S, MachineTypes M) : Lex(S), Machine(M) {}
> +  explicit Parser(StringRef S, MachineTypes M,
> +                  bool B) : Lex(S), Machine(M), MingwDef(B) {}
>  
>    Expected<COFFModuleDefinition> parse() {
>      do {
> @@ -213,9 +220,9 @@
>      }
>  
>      if (Machine == IMAGE_FILE_MACHINE_I386) {
> -      if (!isDecorated(E.Name))
> +      if (!isDecorated(E.Name, MingwDef))
>          E.Name = (std::string("_").append(E.Name));
> -      if (!E.ExtName.empty() && !isDecorated(E.ExtName))
> +      if (!E.ExtName.empty() && !isDecorated(E.ExtName, MingwDef))
>          E.ExtName = (std::string("_").append(E.ExtName));
>      }
>  
> @@ -244,6 +251,12 @@
>          continue;
>        }
>        unget();
> +
> +      if (E.isWeak())
> +        E.SymbolName = E.ExtName;
> +      else
> +        E.SymbolName = E.Name;
> +
>        Info.Exports.push_back(E);
>        return Error::success();
>      }
> @@ -308,11 +321,13 @@
>    std::vector<Token> Stack;
>    MachineTypes Machine;
>    COFFModuleDefinition Info;
> +  bool MingwDef;
>  };
>  
>  Expected<COFFModuleDefinition> parseCOFFModuleDefinition(MemoryBufferRef MB,
> -                                                         MachineTypes Machine) {
> -  return Parser(MB.getBuffer(), Machine).parse();
> +                                                         MachineTypes Machine,
> +                                                         bool MingwDef) {
> +  return Parser(MB.getBuffer(), Machine, MingwDef).parse();
>  }
>  
>  } // namespace object
> Index: lib/Object/COFFImportFile.cpp
> ===================================================================
> --- lib/Object/COFFImportFile.cpp
> +++ lib/Object/COFFImportFile.cpp
> @@ -162,6 +162,10 @@
>    // Library Format.
>    NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
>                                       ImportType Type, ImportNameType NameType);
> +
> +  // Create a weak external file which is described in PE/COFF Aux Format 3.
> +  NewArchiveMember createWeakExternal(std::vector<uint8_t> &Buffer,
> +                                      StringRef Sym, StringRef Weak, bool imp);
>  };
>  } // namespace
>  
> @@ -476,6 +480,89 @@
>    return {MemoryBufferRef(StringRef(Buf, Size), DLLName)};
>  }
>  
> +NewArchiveMember ObjectFactory::createWeakExternal(std::vector<uint8_t> &Buffer,
> +                                                   StringRef Sym, StringRef Weak, bool imp) {
> +  static const uint32_t NumberOfSections = 1;
> +  static const uint32_t NumberOfSymbols = 5;
> +
> +  // COFF Header
> +  coff_file_header Header{
> +      u16(0), u16(NumberOfSections), u32(0),
> +      u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))),
> +      u32(NumberOfSymbols), u16(0),
> +      u16(0),
> +  };
> +  append(Buffer, Header);
> +
> +  // Section Header Table
> +  static const coff_section SectionTable[NumberOfSections] = {
> +      {{'.', 'd', 'r', 'e', 'c', 't', 'v', 'e'},
> +       u32(0),
> +       u32(0),
> +       u32(0),
> +       u32(0),
> +       u32(0),
> +       u32(0),
> +       u16(0),
> +       u16(0),
> +       u32(IMAGE_SCN_LNK_INFO  | IMAGE_SCN_LNK_REMOVE)}
> +     };
> +  append(Buffer, SectionTable);
> +
> +  // Symbol Table
> +  coff_symbol16 SymbolTable[NumberOfSymbols] = {
> +       {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}},
> +       u32(0),
> +       u16(0xFFFF),
> +       u16(0),
> +       IMAGE_SYM_CLASS_STATIC,
> +       0},
> +       {{{'@', 'f', 'e', 'a', 't', '.', '0', '0'}},
> +       u32(0),
> +       u16(0xFFFF),
> +       u16(0),
> +       IMAGE_SYM_CLASS_STATIC,
> +       0},
> +      {{{0, 0, 0, 0, 0, 0, 0, 0}},
> +       u32(0),
> +       u16(0),
> +       u16(0),
> +       IMAGE_SYM_CLASS_EXTERNAL,
> +       0},
> +      {{{0, 0, 0, 0, 0, 0, 0, 0}},
> +       u32(0),
> +       u16(0),
> +       u16(0),
> +       IMAGE_SYM_CLASS_WEAK_EXTERNAL,
> +       1},
> +      {{{2, 0, 0, 0, 3, 0, 0, 0}},
> +       u32(0),
> +       u16(0),
> +       u16(0),
> +       uint8_t(0),
> +       0},
> +  };
> +  reinterpret_cast<StringTableOffset &>(SymbolTable[2].Name).Offset =
> +      sizeof(uint32_t);
> +
> +  //__imp_ String Table
> +  if(imp) {
> +    reinterpret_cast<StringTableOffset &>(SymbolTable[3].Name).Offset =
> +      sizeof(uint32_t) + Sym.size() + 1 + 6;
> +    writeStringTable(Buffer, {std::string("__imp_").append(Sym),
> +                              std::string("__imp_").append(Weak)});
> +  } else {
> +    reinterpret_cast<StringTableOffset &>(SymbolTable[3].Name).Offset =
> +      sizeof(uint32_t) + Sym.size() + 1;
> +    writeStringTable(Buffer, {Sym, Weak});
> +  }
> +  append(Buffer, SymbolTable);
> +
> +  StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
> +  return {MemoryBufferRef{F, DLLName}};
> +
> +}
> +
>  std::error_code writeImportLibrary(StringRef DLLName, StringRef Path,
>                                     ArrayRef<COFFShortExport> Exports,
>                                     MachineTypes Machine) {
> @@ -496,6 +583,14 @@
>      if (E.Private)
>        continue;
>  
> +    if (E.isWeak()) {
> +      std::vector<uint8_t> *WeakBuffer1 = new std::vector<uint8_t>();
> +      std::vector<uint8_t> *WeakBuffer2 = new std::vector<uint8_t>();
> +      Members.push_back(OF.createWeakExternal(*WeakBuffer1, E.Name, E.ExtName, false));
> +      Members.push_back(OF.createWeakExternal(*WeakBuffer2, E.Name, E.ExtName, true));
> +      continue;
> +    }
> +
>      ImportType ImportType = IMPORT_CODE;
>      if (E.Data)
>        ImportType = IMPORT_DATA;
> Index: lib/Object/ArchiveWriter.cpp
> ===================================================================
> --- lib/Object/ArchiveWriter.cpp
> +++ lib/Object/ArchiveWriter.cpp
> @@ -314,7 +314,8 @@
>          continue;
>        if (!(Symflags & object::SymbolRef::SF_Global))
>          continue;
> -      if (Symflags & object::SymbolRef::SF_Undefined)
> +      if (Symflags & object::SymbolRef::SF_Undefined &&
> +          !(Symflags & object::SymbolRef::SF_Weak))
>          continue;

This does look wrong for ELF. In any case, I will just check in a
testcase for ELF that will show the issue.

Cheers,
Rafael


More information about the llvm-commits mailing list