summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
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/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
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/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp')
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp150
1 files changed, 150 insertions, 0 deletions
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
OpenPOWER on IntegriCloud