summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2013-06-17 18:43:13 +0000
committerRui Ueyama <ruiu@google.com>2013-06-17 18:43:13 +0000
commitb24241bae3ba06a055493759ef093db83aa5033c (patch)
tree4c47195cae6156234a42a969c27b1c6e16235dae /lld
parent249f9277a414b79fc121666c61059607210e60d2 (diff)
downloadbcm5719-llvm-b24241bae3ba06a055493759ef093db83aa5033c.tar.gz
bcm5719-llvm-b24241bae3ba06a055493759ef093db83aa5033c.zip
[PECOFF] Implement the reader for the import library.
This is the first patch toward full DLL support. With this patch, lld can read .lib file for a DLL. Reviewers: Bigcheese CC: llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D987 llvm-svn: 184101
Diffstat (limited to 'lld')
-rw-r--r--lld/lib/ReaderWriter/PECOFF/CMakeLists.txt1
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp4
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp150
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.h34
-rw-r--r--lld/test/pecoff/Inputs/dynamic.dllbin0 -> 32256 bytes
-rw-r--r--lld/test/pecoff/Inputs/dynamic.libbin0 -> 1792 bytes
-rw-r--r--lld/test/pecoff/Inputs/main.obj (renamed from lld/test/pecoff/Inputs/static-main.obj)bin568 -> 568 bytes
-rw-r--r--lld/test/pecoff/importlib.test12
-rw-r--r--lld/test/pecoff/lib.test2
-rw-r--r--lld/test/pecoff/multi.test2
10 files changed, 202 insertions, 3 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/CMakeLists.txt b/lld/lib/ReaderWriter/PECOFF/CMakeLists.txt
index a9c7e68dccc..a10bf02093b 100644
--- a/lld/lib/ReaderWriter/PECOFF/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/PECOFF/CMakeLists.txt
@@ -1,6 +1,7 @@
add_lld_library(lldPECOFF
PECOFFTargetInfo.cpp
ReaderCOFF.cpp
+ ReaderImportHeader.cpp
WriterPECOFF.cpp
)
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
index 1b43a1517fb..f6c3e7af24f 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -9,6 +9,8 @@
#define DEBUG_TYPE "ReaderCOFF"
+#include "ReaderImportHeader.h"
+
#include "lld/Core/File.h"
#include "lld/ReaderWriter/Reader.h"
#include "lld/ReaderWriter/ReaderArchive.h"
@@ -596,7 +598,7 @@ public:
return parseCOFFFile(mb, result);
if (fileType == llvm::sys::fs::file_magic::archive)
return _readerArchive.parseFile(mb, result);
- return make_error_code(llvm::object::object_error::invalid_file_type);
+ return lld::coff::parseCOFFImportLibrary(_targetInfo, mb, result);
}
private:
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
new file mode 100644
index 00000000000..200c7bbc6ff
--- /dev/null
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
@@ -0,0 +1,150 @@
+//===- lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp ---------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file \brief This file provides a way to read an import library
+/// member in a .lib file.
+///
+/// In Windows, archive files with .lib file extension serve two different
+/// purposes.
+///
+/// - For static linking: An archive file in this use case contains multiple
+/// normal .obj files and is used for static linking. This is the same
+/// usage as .a file in Unix.
+///
+/// - For dynamic linking: An archive file in this case contains pseudo .obj
+/// files to describe exported symbols of a DLL. Each .obj file in an archive
+/// has a name of an exported symbol and a DLL filename from which the symbol
+/// can be imported. When you link a DLL on Windows, you pass the name of the
+/// .lib file for the DLL instead of the DLL filename itself. That is the
+/// Windows way of linking a shared library.
+///
+/// This file contains a function to parse the pseudo object file.
+///
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "ReaderImportHeader"
+
+#include "lld/Core/File.h"
+#include "lld/Core/Error.h"
+#include "lld/Core/SharedLibraryAtom.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+#include <map>
+#include <vector>
+#include <cstring>
+
+using namespace lld;
+using namespace llvm;
+
+namespace lld {
+namespace coff {
+
+namespace {
+
+class COFFDynamicAtom : public SharedLibraryAtom {
+public:
+ COFFDynamicAtom(File &file, StringRef symbolName, StringRef dllName)
+ : _owningFile(file), _symbolName(symbolName), _dllName(dllName) {}
+
+ virtual const File &file() const { return _owningFile; }
+ virtual StringRef name() const { return _symbolName; }
+ virtual StringRef loadName() const { return _dllName; }
+ virtual bool canBeNullAtRuntime() const { return true; }
+
+private:
+ const File &_owningFile;
+ StringRef _symbolName;
+ StringRef _dllName;
+};
+
+class FileImportLibrary : public File {
+public:
+ FileImportLibrary(const TargetInfo &ti,
+ std::unique_ptr<llvm::MemoryBuffer> mb,
+ llvm::error_code &ec)
+ : File(mb->getBufferIdentifier(), kindSharedLibrary), _targetInfo(ti) {
+ const char *buf = mb->getBufferStart();
+ const char *end = mb->getBufferEnd();
+
+ // The size of the string that follows the header.
+ uint32_t dataSize =
+ *reinterpret_cast<const support::ulittle32_t *>(buf + 12);
+
+ // Check if the total size is valid. The file header is 20 byte long.
+ if (end - buf != 20 + dataSize) {
+ ec = make_error_code(native_reader_error::unknown_file_format);
+ return;
+ }
+
+ StringRef symbolName(buf + 20);
+ StringRef dllName(buf + 20 + symbolName.size() + 1);
+
+ auto *atom = new (allocator.Allocate<COFFDynamicAtom>())
+ COFFDynamicAtom(*this, symbolName, dllName);
+ _sharedLibraryAtoms._atoms.push_back(atom);
+ ec = error_code::success();
+ }
+
+ virtual const atom_collection<DefinedAtom> &defined() const {
+ return _noDefinedAtoms;
+ }
+
+ virtual const atom_collection<UndefinedAtom> &undefined() const {
+ return _noUndefinedAtoms;
+ }
+
+ virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
+ return _sharedLibraryAtoms;
+ }
+
+ virtual const atom_collection<AbsoluteAtom> &absolute() const {
+ return _noAbsoluteAtoms;
+ }
+
+ virtual const TargetInfo &getTargetInfo() const { return _targetInfo; }
+
+private:
+ atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+ const TargetInfo &_targetInfo;
+ mutable llvm::BumpPtrAllocator allocator;
+};
+
+} // end anonymous namespace
+
+error_code parseCOFFImportLibrary(const TargetInfo &targetInfo,
+ std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File> > &result) {
+ // Check the file magic.
+ const char *buf = mb->getBufferStart();
+ const char *end = mb->getBufferEnd();
+ if (end - buf < 20 || memcmp(buf, "\0\0\xFF\xFF", 4))
+ return make_error_code(native_reader_error::unknown_file_format);
+
+ error_code ec;
+ auto file = std::unique_ptr<File>(
+ new FileImportLibrary(targetInfo, std::move(mb), ec));
+ if (ec)
+ return ec;
+ result.push_back(std::move(file));
+ return error_code::success();
+}
+
+} // end namespace coff
+} // end namespace lld
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.h b/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.h
new file mode 100644
index 00000000000..323d8eec8f4
--- /dev/null
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.h
@@ -0,0 +1,34 @@
+//===- lib/ReaderWriter/PECOFF/ReaderImportHeader.h -----------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_PE_COFF_READER_IMPORT_HEADER_H
+#define LLD_READER_WRITER_PE_COFF_READER_IMPORT_HEADER_H
+
+#include <memory>
+#include <vector>
+
+namespace llvm {
+class MemoryBuffer;
+class error_code;
+}
+
+namespace lld {
+class TargetInfo;
+class File;
+
+namespace coff {
+
+llvm::error_code
+ parseCOFFImportLibrary(const TargetInfo &targetInfo,
+ std::unique_ptr<llvm::MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File> > &result);
+}
+}
+
+#endif
diff --git a/lld/test/pecoff/Inputs/dynamic.dll b/lld/test/pecoff/Inputs/dynamic.dll
new file mode 100644
index 00000000000..c9e76e75691
--- /dev/null
+++ b/lld/test/pecoff/Inputs/dynamic.dll
Binary files differ
diff --git a/lld/test/pecoff/Inputs/dynamic.lib b/lld/test/pecoff/Inputs/dynamic.lib
new file mode 100644
index 00000000000..52d2a230e78
--- /dev/null
+++ b/lld/test/pecoff/Inputs/dynamic.lib
Binary files differ
diff --git a/lld/test/pecoff/Inputs/static-main.obj b/lld/test/pecoff/Inputs/main.obj
index 9d0ec24a063..9d0ec24a063 100644
--- a/lld/test/pecoff/Inputs/static-main.obj
+++ b/lld/test/pecoff/Inputs/main.obj
Binary files differ
diff --git a/lld/test/pecoff/importlib.test b/lld/test/pecoff/importlib.test
new file mode 100644
index 00000000000..419a700f575
--- /dev/null
+++ b/lld/test/pecoff/importlib.test
@@ -0,0 +1,12 @@
+# Verify that lld can handle .lib files. "main.obj" refers _val1 and
+# _val2 that are defined in "dynamic.lib".
+#
+# RUN: lld -flavor link -out %t1 -subsystem console \
+# RUN: -- %p/Inputs/main.obj %p/Inputs/dynamic.lib \
+# RUN: && llvm-objdump -d %t1 | FileCheck %s
+
+CHECK: Disassembly of section .text:
+CHECK: .text:
+CHECK: 1000: a1 00 00 00 00
+CHECK: 1005: 03 05 00 00 00 00
+CHECK: 100b: c3
diff --git a/lld/test/pecoff/lib.test b/lld/test/pecoff/lib.test
index abdb1936fed..9eb4b0b6999 100644
--- a/lld/test/pecoff/lib.test
+++ b/lld/test/pecoff/lib.test
@@ -1,7 +1,7 @@
# Verify that lld can handle a library file.
#
# RUN: lld -flavor link -out %t1 -subsystem console \
-# RUN: -- %p/Inputs/static-main.obj %p/Inputs/static.lib \
+# RUN: -- %p/Inputs/main.obj %p/Inputs/static.lib \
# RUN: && llvm-objdump -d %t1 | FileCheck %s
CHECK: Disassembly of section .text:
diff --git a/lld/test/pecoff/multi.test b/lld/test/pecoff/multi.test
index c53db52d14d..7f7c1247e15 100644
--- a/lld/test/pecoff/multi.test
+++ b/lld/test/pecoff/multi.test
@@ -1,7 +1,7 @@
# Verify that lld can handle multiple input files.
#
# RUN: lld -flavor link -out %t1 -subsystem console \
-# RUN: -- %p/Inputs/static-main.obj %p/Inputs/static-data1.obj \
+# RUN: -- %p/Inputs/main.obj %p/Inputs/static-data1.obj \
# RUN: %p/Inputs/static-data2.obj \
# RUN: && llvm-objdump -d %t1 | FileCheck %s
OpenPOWER on IntegriCloud