<div dir="rtl"><div dir="ltr">Hi Rui,</div><div dir="ltr"><br></div><div dir="ltr">MinGW (gcc) can link against DLL files created by MinGW without an import library. You just need the header and DLL files. See here:</div><div dir="ltr">

<br></div><div dir="ltr"><a href="http://www.mingw.org/wiki/CreateImportLibraries">http://www.mingw.org/wiki/CreateImportLibraries</a><br></div><div dir="ltr"><br></div><div dir="ltr">I hope this helps,</div><div dir="ltr">

<br></div><div dir="ltr">Yaron<br></div><div dir="ltr"><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote"><div dir="ltr">2013/12/13 Rui Ueyama <span dir="ltr"><<a href="mailto:ruiu@google.com" target="_blank">ruiu@google.com</a>></span></div>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ruiu<br>
Date: Fri Dec 13 00:58:27 2013<br>
New Revision: 197212<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=197212&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=197212&view=rev</a><br>
Log:<br>
[PECOFF] Create .edata section for the DLL export table.<br>
<br>
This is the first patch to emit data for the DLL export table. The DLL export<br>
table is the data used by the Windows loader to find the address of exported<br>
function from DLL. With this patch, LLD is able to emit a valid DLL export<br>
table which the Windows loader can interpret and load.<br>
<br>
The data structure of the DLL export table is described in the Microsoft<br>
PE/COFF Specification, section 5.3.<br>
<br>
DLL support is not complete yet; the linker needs to emit an import library<br>
for a DLL, otherwise the linker cannot link against the DLL. We also do not<br>
support export-only-by-ordinal yet.<br>
<br>
Added:<br>
    lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp<br>
    lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.h<br>
    lld/trunk/test/pecoff/Inputs/export.obj.yaml<br>
    lld/trunk/test/pecoff/export.test<br>
Modified:<br>
    lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt<br>
    lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp<br>
    lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt?rev=197212&r1=197211&r2=197212&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt?rev=197212&r1=197211&r2=197212&view=diff</a><br>


==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt (original)<br>
+++ lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt Fri Dec 13 00:58:27 2013<br>
@@ -1,4 +1,5 @@<br>
 add_lld_library(lldPECOFF<br>
+  EdataPass.cpp<br>
   IdataPass.cpp<br>
   PECOFFLinkingContext.cpp<br>
   Pass.cpp<br>
<br>
Added: lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp?rev=197212&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp?rev=197212&view=auto</a><br>


==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp (added)<br>
+++ lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp Fri Dec 13 00:58:27 2013<br>
@@ -0,0 +1,142 @@<br>
+//===- lib/ReaderWriter/PECOFF/EdataPass.cpp ------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "Pass.h"<br>
+#include "EdataPass.h"<br>
+<br>
+#include "lld/Core/File.h"<br>
+#include "lld/Core/Pass.h"<br>
+#include "lld/ReaderWriter/Simple.h"<br>
+#include "llvm/Support/Path.h"<br>
+<br>
+#include <ctime><br>
+<br>
+using lld::pecoff::edata::EdataAtom;<br>
+using llvm::object::export_address_table_entry;<br>
+using llvm::object::export_directory_table_entry;<br>
+<br>
+namespace lld {<br>
+namespace pecoff {<br>
+<br>
+static bool<br>
+getExportedAtoms(const PECOFFLinkingContext &ctx, MutableFile *file,<br>
+                 std::vector<const DefinedAtom *> &ret) {<br>
+  std::map<StringRef, const DefinedAtom *> definedAtoms;<br>
+  for (const DefinedAtom *atom : file->defined())<br>
+    definedAtoms[atom->name()] = atom;<br>
+<br>
+  for (StringRef dllExport : ctx.getDllExports()) {<br>
+    auto it = definedAtoms.find(ctx.decorateSymbol(dllExport));<br>
+    if (it == definedAtoms.end()) {<br>
+      llvm::errs() << "Symbol <" << dllExport<br>
+                   << "> is exported but not defined.\n";<br>
+      return false;<br>
+    }<br>
+    const DefinedAtom *atom = it->second;<br>
+    ret.push_back(atom);<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+static bool compare(const DefinedAtom *a, const DefinedAtom *b) {<br>
+  return a->name().compare(b->name()) < 0;<br>
+}<br>
+<br>
+edata::EdataAtom *<br>
+EdataPass::createAddressTable(const std::vector<const DefinedAtom *> &atoms) {<br>
+  EdataAtom *addressTable = new (_alloc) EdataAtom(<br>
+    _file, sizeof(export_address_table_entry) * atoms.size());<br>
+<br>
+  size_t offset = 0;<br>
+  for (const DefinedAtom *atom : atoms) {<br>
+    addDir32NBReloc(addressTable, atom, offset);<br>
+    offset += sizeof(export_address_table_entry);<br>
+  }<br>
+  return addressTable;<br>
+}<br>
+<br>
+edata::EdataAtom *<br>
+EdataPass::createNamePointerTable(const std::vector<const DefinedAtom *> &atoms,<br>
+                                  MutableFile *file) {<br>
+  EdataAtom *table = new (_alloc) EdataAtom(_file, sizeof(uint32_t) * atoms.size());<br>
+<br>
+  size_t offset = 0;<br>
+  for (const DefinedAtom *atom : atoms) {<br>
+    COFFStringAtom *stringAtom = new (_alloc) COFFStringAtom(<br>
+      _file, _file.getNextOrdinal(), ".edata", atom->name());<br>
+    file->addAtom(*stringAtom);<br>
+    addDir32NBReloc(table, stringAtom, offset);<br>
+    offset += sizeof(uint32_t);<br>
+  }<br>
+  return table;<br>
+}<br>
+<br>
+edata::EdataAtom *EdataPass::createExportDirectoryTable(size_t numEntries) {<br>
+  EdataAtom *ret = new (_alloc) EdataAtom(_file, sizeof(export_directory_table_entry));<br>
+  auto *data = ret->getContents<export_directory_table_entry>();<br>
+  data->TimeDateStamp = time(nullptr);<br>
+  data->OrdinalBase = 1;<br>
+  data->AddressTableEntries = numEntries;<br>
+  data->NumberOfNamePointers = numEntries;<br>
+  return ret;<br>
+}<br>
+<br>
+edata::EdataAtom *<br>
+EdataPass::createOrdinalTable(const std::vector<const DefinedAtom *> &atoms,<br>
+                              const std::vector<const DefinedAtom *> &sortedAtoms) {<br>
+  EdataAtom *ret = new (_alloc) EdataAtom(_file, sizeof(uint16_t) * atoms.size());<br>
+  uint16_t *data = ret->getContents<uint16_t>();<br>
+<br>
+  std::map<const DefinedAtom *, size_t> ordinals;<br>
+  size_t ordinal = 0;<br>
+  for (const DefinedAtom *atom : atoms)<br>
+    ordinals[atom] = ordinal++;<br>
+<br>
+  size_t index = 0;<br>
+  for (const DefinedAtom *atom : sortedAtoms)<br>
+    data[index++] = ordinals[atom];<br>
+  return ret;<br>
+}<br>
+<br>
+void EdataPass::perform(std::unique_ptr<MutableFile> &file) {<br>
+  std::vector<const DefinedAtom *> atoms;<br>
+  if (!getExportedAtoms(_ctx, file.get(), atoms))<br>
+    return;<br>
+  if (atoms.empty())<br>
+    return;<br>
+<br>
+  EdataAtom *table = createExportDirectoryTable(atoms.size());<br>
+  file->addAtom(*table);<br>
+<br>
+  COFFStringAtom *dllName = new (_alloc) COFFStringAtom(<br>
+    _file, _file.getNextOrdinal(),<br>
+    ".edata", llvm::sys::path::filename(_ctx.outputPath()));<br>
+  file->addAtom(*dllName);<br>
+  addDir32NBReloc(table, dllName, offsetof(export_directory_table_entry, NameRVA));<br>
+<br>
+  EdataAtom *addressTable = createAddressTable(atoms);<br>
+  file->addAtom(*addressTable);<br>
+  addDir32NBReloc(table, addressTable,<br>
+                  offsetof(export_directory_table_entry, ExportAddressTableRVA));<br>
+<br>
+  std::vector<const DefinedAtom *> sortedAtoms(atoms);<br>
+  std::sort(sortedAtoms.begin(), sortedAtoms.end(), compare);<br>
+  EdataAtom *namePointerTable = createNamePointerTable(sortedAtoms, file.get());<br>
+  file->addAtom(*namePointerTable);<br>
+  addDir32NBReloc(table, namePointerTable,<br>
+                  offsetof(export_directory_table_entry, NamePointerRVA));<br>
+<br>
+  EdataAtom *ordinalTable = createOrdinalTable(atoms, sortedAtoms);<br>
+  file->addAtom(*ordinalTable);<br>
+  addDir32NBReloc(table, ordinalTable,<br>
+                  offsetof(export_directory_table_entry, OrdinalTableRVA));<br>
+}<br>
+<br>
+} // namespace pecoff<br>
+} // namespace lld<br>
<br>
Added: lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.h?rev=197212&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.h?rev=197212&view=auto</a><br>


==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.h (added)<br>
+++ lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.h Fri Dec 13 00:58:27 2013<br>
@@ -0,0 +1,81 @@<br>
+//===- lib/ReaderWriter/PECOFF/EdataPass.h --------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file \brief This linker pass creates atoms for the DLL export<br>
+/// information. The defined atoms constructed in this pass will go into .edata<br>
+/// section.<br>
+///<br>
+/// For the details of the .edata section format, see Microsoft PE/COFF<br>
+/// Specification section 5.3, The .edata Section.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLD_READER_WRITER_PE_COFF_EDATA_PASS_H<br>
+#define LLD_READER_WRITER_PE_COFF_EDATA_PASS_H<br>
+<br>
+#include "Atoms.h"<br>
+<br>
+#include "lld/Core/File.h"<br>
+#include "lld/Core/Pass.h"<br>
+#include "lld/ReaderWriter/PECOFFLinkingContext.h"<br>
+#include "lld/ReaderWriter/Simple.h"<br>
+#include "llvm/Support/COFF.h"<br>
+<br>
+#include <map><br>
+<br>
+using llvm::COFF::ImportDirectoryTableEntry;<br>
+<br>
+namespace lld {<br>
+namespace pecoff {<br>
+namespace edata {<br>
+<br>
+/// The root class of all edata atoms.<br>
+class EdataAtom : public COFFLinkerInternalAtom {<br>
+public:<br>
+  EdataAtom(VirtualFile &file, size_t size)<br>
+    : COFFLinkerInternalAtom(file, file.getNextOrdinal(),<br>
+                             std::vector<uint8_t>(size)) {}<br>
+<br>
+  virtual SectionChoice sectionChoice() const { return sectionCustomRequired; }<br>
+  virtual StringRef customSectionName() const { return ".edata"; }<br>
+  virtual ContentType contentType() const { return typeData; }<br>
+  virtual ContentPermissions permissions() const { return permR__; }<br>
+<br>
+  template<typename T> T *getContents() const {<br>
+    return (T *)rawContent().data();<br>
+  }<br>
+};<br>
+<br>
+} // namespace edata<br>
+<br>
+class EdataPass : public lld::Pass {<br>
+public:<br>
+  EdataPass(const PECOFFLinkingContext &ctx) : _ctx(ctx), _file(ctx) {}<br>
+<br>
+  virtual void perform(std::unique_ptr<MutableFile> &file);<br>
+<br>
+private:<br>
+  edata::EdataAtom *createExportDirectoryTable(size_t numEntries);<br>
+  edata::EdataAtom *createAddressTable(<br>
+    const std::vector<const DefinedAtom *> &atoms);<br>
+  edata::EdataAtom *createNamePointerTable(<br>
+    const std::vector<const DefinedAtom *> &atoms, MutableFile *file);<br>
+  edata::EdataAtom *createOrdinalTable(<br>
+    const std::vector<const DefinedAtom *> &atoms,<br>
+    const std::vector<const DefinedAtom *> &sortedAtoms);<br>
+<br>
+  const PECOFFLinkingContext &_ctx;<br>
+  VirtualFile _file;<br>
+  mutable llvm::BumpPtrAllocator _alloc;<br>
+};<br>
+<br>
+} // namespace pecoff<br>
+} // namespace lld<br>
+<br>
+#endif<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=197212&r1=197211&r2=197212&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=197212&r1=197211&r2=197212&view=diff</a><br>


==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Fri Dec 13 00:58:27 2013<br>
@@ -8,6 +8,7 @@<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "Atoms.h"<br>
+#include "EdataPass.h"<br>
 #include "GroupedSectionsPass.h"<br>
 #include "IdataPass.h"<br>
 #include "LinkerGeneratedSymbolFile.h"<br>
@@ -249,6 +250,7 @@ uint32_t PECOFFLinkingContext::getSectio<br>
<br>
 void PECOFFLinkingContext::addPasses(PassManager &pm) {<br>
   pm.add(std::unique_ptr<Pass>(new pecoff::SetSubsystemPass(*this)));<br>
+  pm.add(std::unique_ptr<Pass>(new pecoff::EdataPass(*this)));<br>
   pm.add(std::unique_ptr<Pass>(new pecoff::IdataPass(*this)));<br>
   pm.add(std::unique_ptr<Pass>(new LayoutPass()));<br>
   pm.add(std::unique_ptr<Pass>(new pecoff::GroupedSectionsPass()));<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp?rev=197212&r1=197211&r2=197212&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp?rev=197212&r1=197211&r2=197212&view=diff</a><br>


==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp Fri Dec 13 00:58:27 2013<br>
@@ -885,6 +885,9 @@ void ExecutableWriter::build(const File<br>
     if (section->getSectionName() == ".idata.d")<br>
       dataDirectory->setField(DataDirectoryIndex::IMPORT_TABLE,<br>
                               section->getVirtualAddress(), section->size());<br>
+    if (section->getSectionName() == ".edata")<br>
+      dataDirectory->setField(DataDirectoryIndex::EXPORT_TABLE,<br>
+                              section->getVirtualAddress(), section->size());<br>
   }<br>
<br>
   // Now that we know the size and file offset of sections. Set the file<br>
<br>
Added: lld/trunk/test/pecoff/Inputs/export.obj.yaml<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/export.obj.yaml?rev=197212&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/export.obj.yaml?rev=197212&view=auto</a><br>


==============================================================================<br>
--- lld/trunk/test/pecoff/Inputs/export.obj.yaml (added)<br>
+++ lld/trunk/test/pecoff/Inputs/export.obj.yaml Fri Dec 13 00:58:27 2013<br>
@@ -0,0 +1,31 @@<br>
+---<br>
+header:<br>
+  Machine:         IMAGE_FILE_MACHINE_I386<br>
+  Characteristics: []<br>
+sections:<br>
+  - Name:            .text<br>
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]<br>
+    Alignment:       4<br>
+    SectionData:     B800000000506800000000680000000050E80000000050E800000000<br>
+symbols:<br>
+  - Name:            .text<br>
+    Value:           0<br>
+    SectionNumber:   1<br>
+    SimpleType:      IMAGE_SYM_TYPE_NULL<br>
+    ComplexType:     IMAGE_SYM_DTYPE_NULL<br>
+    StorageClass:    IMAGE_SYM_CLASS_STATIC<br>
+    NumberOfAuxSymbols: 1<br>
+    AuxiliaryData:   1C0000000400000000000000000000000000<br>
+  - Name:            _init<br>
+    Value:           0<br>
+    SectionNumber:   1<br>
+    SimpleType:      IMAGE_SYM_TYPE_NULL<br>
+    ComplexType:     IMAGE_SYM_DTYPE_NULL<br>
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL<br>
+  - Name:            _exportfn<br>
+    Value:           8<br>
+    SectionNumber:   1<br>
+    SimpleType:      IMAGE_SYM_TYPE_NULL<br>
+    ComplexType:     IMAGE_SYM_DTYPE_NULL<br>
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL<br>
+...<br>
<br>
Added: lld/trunk/test/pecoff/export.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/export.test?rev=197212&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/export.test?rev=197212&view=auto</a><br>


==============================================================================<br>
--- lld/trunk/test/pecoff/export.test (added)<br>
+++ lld/trunk/test/pecoff/export.test Fri Dec 13 00:58:27 2013<br>
@@ -0,0 +1,12 @@<br>
+# RUN: yaml2obj %p/Inputs/export.obj.yaml > %t.obj<br>
+#<br>
+# RUN: lld -flavor link /out:%t.dll /dll /subsystem:console /entry:_init \<br>
+# RUN:   /export:exportfn -- %t.obj<br>
+# RUN: llvm-objdump -s %t.dll | FileCheck %s<br>
+<br>
+CHECK:      Contents of section .edata:<br>
+CHECK-NEXT:  1000 00000000 {{........}} 00000000 28100000<br>
+CHECK-NEXT:  1010 01000000 01000000 01000000 3c100000<br>
+CHECK-NEXT:  1020 40100000 4e100000 6578706f 72742e74<br>
+CHECK-NEXT:  1030 6573742e 746d702e 646c6c00 08200000<br>
+CHECK-NEXT:  1040 44100000 5f657870 6f727466 6e000000<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>