[llvm-commits] [lld] Supporting archive libraries in lld
Shankar Easwaran
shankare at codeaurora.org
Tue Nov 6 08:30:26 PST 2012
Hi Nick, Michael,
I incorporated your comments in lld / llvm for supporting reading
archive libraries.
Please look at the new changes and let me know if you are ok to commit
this in.
Thanks
Shankar Easwaran
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation
-------------- next part --------------
Index: tools/lld-core/lld-core.cpp
===================================================================
--- tools/lld-core/lld-core.cpp (revision 166441)
+++ tools/lld-core/lld-core.cpp (working copy)
@@ -12,6 +12,7 @@
#include "lld/Core/Pass.h"
#include "lld/Core/Resolver.h"
#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
#include "lld/ReaderWriter/ReaderNative.h"
#include "lld/ReaderWriter/ReaderYAML.h"
#include "lld/ReaderWriter/ReaderELF.h"
@@ -76,6 +77,10 @@
llvm::cl::desc("Any undefined symbols at end is an error"));
llvm::cl::opt<bool>
+cmdLineForceLoad("force-load",
+ llvm::cl::desc("force load all members of the archive"));
+
+llvm::cl::opt<bool>
cmdLineCommonsSearchArchives("commons-search-archives",
llvm::cl::desc("Tentative definitions trigger archive search"));
@@ -214,6 +219,8 @@
// create object to mange input files
InputFiles inputFiles;
+ ReaderOptionsArchive readerOptionsArchive(cmdLineForceLoad);
+
// read input files into in-memory File objects
TestingReaderOptionsYAML readerOptionsYAML;
@@ -231,7 +238,9 @@
reader = createReaderPECOFF(lld::ReaderOptionsPECOFF());
break;
case readerELF:
- reader = createReaderELF(lld::ReaderOptionsELF());
+ reader = createReaderELF(lld::ReaderOptionsELF(),
+ readerOptionsArchive);
+
break;
default:
reader = createReaderYAML(readerOptionsYAML);
Index: include/lld/ReaderWriter/ReaderELF.h
===================================================================
--- include/lld/ReaderWriter/ReaderELF.h (revision 166441)
+++ include/lld/ReaderWriter/ReaderELF.h (working copy)
@@ -11,6 +11,7 @@
#define LLD_READERWRITER_READER_ELF_H_
#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
#include "lld/Core/LLVM.h"
@@ -56,7 +57,8 @@
/// ReaderOptionsELF object supplied, so the objects object must not be
/// destroyed before the Reader object.
///
-Reader* createReaderELF(const ReaderOptionsELF &options);
+Reader* createReaderELF(const ReaderOptionsELF &options,
+ ReaderOptionsArchive &optionsArchive);
Index: include/lld/ReaderWriter/ReaderArchive.h
===================================================================
--- include/lld/ReaderWriter/ReaderArchive.h (revision 0)
+++ include/lld/ReaderWriter/ReaderArchive.h (revision 0)
@@ -0,0 +1,84 @@
+//===- ReaderWriter/ReaderArchive.h - Archive Library Reader ------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------------===//
+
+#ifndef LLD_READER_ARCHIVE_H
+#define LLD_READER_ARCHIVE_H
+
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Object/Archive.h"
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
+#include <memory>
+#include <bits/unique_ptr.h>
+#include <vector>
+
+namespace lld
+{
+///
+/// The ReaderOptionsArchive encapsulates the options used by the ReaderArchive.
+/// The option objects are the only way to control the behaviour of Readers.
+///
+class ReaderOptionsArchive
+{
+public:
+ ReaderOptionsArchive(bool is_force_load=false): _isForceLoad(is_force_load),
+ _reader(nullptr)
+ { }
+
+ bool isForceLoad() const {
+ return _isForceLoad;
+ }
+
+ Reader *reader() const {
+ return _reader;
+ }
+
+ void setReader(Reader *r) {
+ _reader = r;
+ }
+
+private:
+ bool _isForceLoad;
+ Reader *_reader;
+};
+
+// ReaderArchive is a class for reading archive libraries
+class ReaderArchive final
+{
+public:
+ ReaderArchive(ReaderOptionsArchive &options) : _options(options),
+ _archive()
+ { }
+
+ // Returns a vector of Files that are contained in the archive file
+ // pointed to by the Memorybuffer
+ virtual error_code parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
+ std::vector<std::unique_ptr<File>> &result);
+
+ // Returns a vector of Files that are contained in the archive file
+ // specified by path
+ virtual error_code parseFile(StringRef path,
+ std::vector<std::unique_ptr<File>> &result);
+
+ virtual ~ReaderArchive() { }
+
+private:
+ ReaderOptionsArchive &_options;
+ std::unique_ptr<llvm::object::Archive> _archive;
+};
+
+} // namespace lld
+
+#endif // LLD_READER_ARCHIVE_H
Index: include/lld/Core/FileArchive.h
===================================================================
--- include/lld/Core/FileArchive.h (revision 0)
+++ include/lld/Core/FileArchive.h (revision 0)
@@ -0,0 +1,142 @@
+//===- Core/FileArchive.h - Support static library -----------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_FILE_ARCHIVE_FILE_H_
+#define LLD_CORE_FILE_ARCHIVE_FILE_H_
+
+#include "lld/ReaderWriter/ReaderArchive.h"
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Object/Archive.h"
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+
+namespace lld {
+
+// The FileArchive class represents an Archive Library file
+class FileArchive : public ArchiveLibraryFile {
+public:
+
+ virtual ~FileArchive() { }
+
+ /// Check if any member of the archive contains an Atom with the
+ /// specified name and return the File object for that member, or nullptr.
+ virtual const File *find(StringRef name, bool dataSymbolOnly) const {
+ error_code ec;
+ llvm::object::Archive::child_iterator ci;
+
+ if ((ec = (_archive.get()->findSym(name, ci))))
+ return nullptr;
+
+ if (dataSymbolOnly && (ec = isDataSymbol(ci->getBuffer(), name)))
+ return nullptr;
+
+ std::vector<std::unique_ptr<File>> result;
+
+ if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
+ (ci->getBuffer()), result)))
+ return nullptr;
+
+ // give up the pointer so that this object no longer manages it
+ for (std::unique_ptr<File> &f : result) {
+ return f.release();
+ }
+
+ return nullptr;
+ }
+
+ virtual void addAtom(const Atom&) {
+ llvm_unreachable("cannot add atoms to archive files");
+ }
+
+ virtual const atom_collection<DefinedAtom> &defined() const {
+ return _definedAtoms;
+ }
+
+ virtual const atom_collection<UndefinedAtom> &undefined() const {
+ return _undefinedAtoms;
+ }
+
+ virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
+ return _sharedLibraryAtoms;
+ }
+
+ virtual const atom_collection<AbsoluteAtom> &absolute() const {
+ return _absoluteAtoms;
+ }
+
+protected:
+ error_code isDataSymbol(MemoryBuffer *mb, StringRef symbol) const
+ {
+ llvm::object::ObjectFile *obj =
+ llvm::object::ObjectFile::createObjectFile(mb);
+ error_code ec;
+ llvm::object::SymbolRef::Type symtype;
+ uint32_t symflags;
+ llvm::object::symbol_iterator ibegin = obj->begin_symbols();
+ llvm::object::symbol_iterator iend = obj->end_symbols();
+ StringRef symbolname;
+
+ for (llvm::object::symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
+ if (ec) return ec;
+
+ // Get symbol name
+ if ((ec = (i->getName(symbolname)))) return ec;
+
+ if (symbolname != symbol)
+ continue;
+
+ // Get symbol flags
+ if ((ec = (i->getFlags(symflags)))) return ec;
+
+ if (symflags <= llvm::object::SymbolRef::SF_Undefined)
+ continue;
+
+ // Get Symbol Type
+ if ((ec = (i->getType(symtype)))) return ec;
+
+ if (symtype == llvm::object::SymbolRef::ST_Data) {
+ return error_code::success();
+ }
+ }
+ return llvm::object::object_error::parse_failed;
+ }
+
+private:
+ llvm::MemoryBuffer *_mb;
+ std::unique_ptr<llvm::object::Archive> _archive;
+ const ReaderOptionsArchive _options;
+ atom_collection_vector<DefinedAtom> _definedAtoms;
+ atom_collection_vector<UndefinedAtom> _undefinedAtoms;
+ atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+ atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+
+public:
+ /// only subclasses of ArchiveLibraryFile can be instantiated
+ explicit FileArchive(llvm::MemoryBuffer *mb,
+ const ReaderOptionsArchive &options,
+ error_code &ec)
+ :ArchiveLibraryFile(mb->getBufferIdentifier()),
+ _mb(mb),
+ _archive(nullptr),
+ _options(options) {
+ auto *archive_obj = new llvm::object::Archive(mb, ec);
+ if (ec)
+ return;
+ _archive.reset(archive_obj);
+ }
+};
+
+} // namespace lld
+
+#endif // LLD_CORE_FILE_ARCHIVE_FILE_H_
Index: lib/ReaderWriter/ReaderArchive.cpp
===================================================================
--- lib/ReaderWriter/ReaderArchive.cpp (revision 0)
+++ lib/ReaderWriter/ReaderArchive.cpp (revision 0)
@@ -0,0 +1,56 @@
+//===- lib/ReaderWriter/ReaderArchive.cpp - Archive Library Reader--------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "lld/ReaderWriter/ReaderArchive.h"
+#include "lld/Core/FileArchive.h"
+
+namespace lld
+{
+ // Returns a vector of Files that are contained in the archive file
+ error_code ReaderArchive::parseFile(StringRef path,
+ std::vector<std::unique_ptr<File>> &result) {
+ error_code ec;
+ OwningPtr<llvm::MemoryBuffer> opmb;
+ if ((ec = llvm::MemoryBuffer::getFile(path, opmb)))
+ return ec;
+
+ std::unique_ptr<MemoryBuffer> mb(opmb.take());
+
+ return parseFile(std::move(mb), result);
+ }
+
+ // Returns a vector of Files that are contained in the archive file
+ // pointed to by the MemoryBuffer
+ error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
+ std::vector<std::unique_ptr<File>> &result) {
+ error_code ec;
+
+ if (_options.isForceLoad())
+ {
+ _archive.reset(new llvm::object::Archive(mb.get(), ec));
+ if (ec)
+ return ec;
+
+ for (auto mf = _archive->begin_children(),
+ me = _archive->end_children(); mf != me; ++mf)
+ {
+ if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
+ (mf->getBuffer()), result)))
+ return ec;
+ }
+ } else {
+ std::unique_ptr<File> f;
+ f.reset(new FileArchive(mb.release(), _options, ec));
+ if (ec)
+ return ec;
+
+ result.push_back(std::move(f));
+ }
+ return llvm::error_code::success();
+ }
+}
Index: lib/ReaderWriter/ELF/ReaderELF.cpp
===================================================================
--- lib/ReaderWriter/ELF/ReaderELF.cpp (revision 166441)
+++ lib/ReaderWriter/ELF/ReaderELF.cpp (working copy)
@@ -12,9 +12,9 @@
//
//===----------------------------------------------------------------------===//
#include "lld/ReaderWriter/ReaderELF.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
-
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
@@ -30,6 +30,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
+#include "llvm/Support/Path.h"
#include <map>
@@ -751,20 +752,36 @@
class ReaderELF: public Reader {
public:
- ReaderELF(const ReaderOptionsELF &) {}
+ ReaderELF(const ReaderOptionsELF &readerELFOptions,
+ ReaderOptionsArchive &readerOptionsArchive)
+ : _readerELFOptions(readerELFOptions),
+ _readerOptionsArchive(readerOptionsArchive)
+ {
+ _readerOptionsArchive.setReader(this);
+ _readerArchive.reset(new ReaderArchive(_readerOptionsArchive));
+ }
+
error_code parseFile(std::unique_ptr<MemoryBuffer> mb, std::vector<
std::unique_ptr<File> > &result) {
std::pair<unsigned char, unsigned char> Ident =
llvm::object::getElfArchType(&*mb);
llvm::error_code ec;
+
+ llvm::sys::LLVMFileType fileType =
+ llvm::sys::IdentifyFileType(mb->getBufferStart(),
+ static_cast<unsigned>(mb->getBufferSize()));
+
+ std::unique_ptr<File> f;
+
+ switch (fileType) {
+
+ case llvm::sys::ELF_Relocatable_FileType:
// Instantiate the correct FileELF template instance
// based on the Ident pair. Once the File is created
// we push the file to the vector of files already
// created during parser's life.
- std::unique_ptr<File> f;
-
if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
== llvm::ELF::ELFDATA2LSB) {
f.reset(new FileELF<llvm::support::little, false>(std::move(mb), ec));
@@ -781,13 +798,29 @@
== llvm::ELF::ELFDATA2LSB) {
f.reset(new FileELF<llvm::support::little, true> (std::move(mb), ec));
}
+ if (!ec)
+ result.push_back(std::move(f));
+ break;
+
+ case llvm::sys::Archive_FileType:
+ ec = _readerArchive->parseFile(std::move(mb), result);
+ break;
+
+ default:
+ llvm_unreachable("not supported format");
+ break;
+ }
if (ec)
return ec;
- result.push_back(std::move(f));
return error_code::success();
}
+
+private:
+ const ReaderOptionsELF &_readerELFOptions;
+ ReaderOptionsArchive &_readerOptionsArchive;
+ std::unique_ptr<ReaderArchive> _readerArchive;
};
} // namespace anonymous
@@ -800,8 +833,9 @@
ReaderOptionsELF::~ReaderOptionsELF() {
}
-Reader *createReaderELF(const ReaderOptionsELF &options) {
- return new ReaderELF(options);
+Reader *createReaderELF(const ReaderOptionsELF &options,
+ ReaderOptionsArchive &optionsArchive) {
+ return new ReaderELF(options, optionsArchive);
}
} // namespace LLD
Index: lib/ReaderWriter/CMakeLists.txt
===================================================================
--- lib/ReaderWriter/CMakeLists.txt (revision 166441)
+++ lib/ReaderWriter/CMakeLists.txt (working copy)
@@ -6,4 +6,5 @@
add_lld_library(lldReaderWriter
Reader.cpp
Writer.cpp
+ ReaderArchive.cpp
)
-------------- next part --------------
Index: test/Object/Inputs/coff_archive.lib
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: test/Object/Inputs/coff_archive.lib
___________________________________________________________________
Added: svn:executable
+ *
Added: svn:mime-type
+ application/octet-stream
Index: test/Object/Inputs/liblong_filenames.a
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: test/Object/Inputs/liblong_filenames.a
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: test/Object/Inputs/libsimple_archive.a
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: test/Object/Inputs/libsimple_archive.a
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: test/Object/simple-archive.test
===================================================================
--- test/Object/simple-archive.test (revision 0)
+++ test/Object/simple-archive.test (revision 0)
@@ -0,0 +1,12 @@
+#
+# Check if the index is appearing properly in the output file
+#
+RUN: llvm-nm -s %p/Inputs/libsimple_archive.a | FileCheck -check-prefix=CHECKIDX %s
+
+CHECKIDX: Archive map
+CHECKIDX: abcdefghijklmnopqrstuvwxyz12345678 in 1.o
+CHECKIDX: main in 1.o
+CHECKIDX: 1.o:
+CHECKIDX: 00000000 D abcdefghijklmnopqrstuvwxyz12345678
+CHECKIDX: U fn1
+CHECKIDX: 00000000 T main
Index: test/Object/archive-long-index.test
===================================================================
--- test/Object/archive-long-index.test (revision 0)
+++ test/Object/archive-long-index.test (revision 0)
@@ -0,0 +1,40 @@
+#
+# Check if the index is appearing properly in the output file
+#
+RUN: llvm-nm -s %p/Inputs/liblong_filenames.a | FileCheck -check-prefix=CHECKIDX %s
+
+CHECKIDX: Archive map
+CHECKIDX: abcdefghijklmnopqrstuvwxyz12345678 in 1.o
+CHECKIDX: main in 1.o
+CHECKIDX: fn1 in 2.o
+CHECKIDX: fn3 in 3.o
+CHECKIDX: fn1 in 3.o
+CHECKIDX: shankar in 4.o
+CHECKIDX: a in 5.o
+CHECKIDX: b in 6.o
+CHECKIDX: a in abcdefghijklmnopqrstuvwxyz1.o
+CHECKIDX: b in abcdefghijklmnopqrstuvwxyz2.o
+CHECKIDX: bda in abcdefghijklmnopqrstuvwxyz2.o
+CHECKIDX: b in abcdefghijklmnopq.o
+CHECKIDX: 1.o:
+CHECKIDX: 00000000 D abcdefghijklmnopqrstuvwxyz12345678
+CHECKIDX: U bda
+CHECKIDX: 00000000 T main
+CHECKIDX: 2.o:
+CHECKIDX: 00000000 T fn1
+CHECKIDX: 3.o:
+CHECKIDX: 0000000b T fn1
+CHECKIDX: 00000000 T fn3
+CHECKIDX: 4.o:
+CHECKIDX: C shankar
+CHECKIDX: 5.o:
+CHECKIDX: C a
+CHECKIDX: 6.o:
+CHECKIDX: C b
+CHECKIDX: abcdefghijklmnopqrstuvwxyz1.o:
+CHECKIDX: C a
+CHECKIDX: abcdefghijklmnopqrstuvwxyz2.o:
+CHECKIDX: C b
+CHECKIDX: 00000000 T bda
+CHECKIDX: abcdefghijklmnopq.o:
+CHECKIDX: C b
Index: test/Object/coff-archive.test
===================================================================
--- test/Object/coff-archive.test (revision 0)
+++ test/Object/coff-archive.test (revision 0)
@@ -0,0 +1,225 @@
+#
+# Check if the index is appearing properly in the output file
+#
+RUN: llvm-nm -s %p/Inputs/coff_archive.lib | FileCheck -check-prefix=CHECKIDX %s
+
+CHECKIDX: Archive map
+CHECKIDX: ??0invalid_argument at std@@QAE at PBD@Z in Debug\mymath.obj
+CHECKIDX: ??0logic_error at std@@QAE at PBD@Z in Debug\mymath.obj
+CHECKIDX: ??1invalid_argument at std@@UAE at XZ in Debug\mymath.obj
+CHECKIDX: ??1logic_error at std@@UAE at XZ in Debug\mymath.obj
+CHECKIDX: ??_7invalid_argument at std@@6B@ in Debug\mymath.obj
+CHECKIDX: ??_7logic_error at std@@6B@ in Debug\mymath.obj
+CHECKIDX: ??_C at _0BC@IHENMCGI at b?5cannot?5be?5zero?$CB?$AA@ in Debug\mymath.obj
+CHECKIDX: ??_Ginvalid_argument at std@@UAEPAXI at Z in Debug\mymath.obj
+CHECKIDX: ??_Glogic_error at std@@UAEPAXI at Z in Debug\mymath.obj
+CHECKIDX: ??_R0?AVexception at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0?AVinvalid_argument at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0?AVlogic_error at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0PAVexception at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0PAVinvalid_argument at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0PAVlogic_error at std@@@8 in Debug\mymath.obj
+CHECKIDX: ??_R0PAX at 8 in Debug\mymath.obj
+CHECKIDX: ??_R1A@?0A at EA@exception at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R1A@?0A at EA@invalid_argument at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R1A@?0A at EA@logic_error at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R2exception at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R2invalid_argument at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R2logic_error at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R3exception at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R3invalid_argument at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R3logic_error at std@@8 in Debug\mymath.obj
+CHECKIDX: ??_R4invalid_argument at std@@6B@ in Debug\mymath.obj
+CHECKIDX: ??_R4logic_error at std@@6B@ in Debug\mymath.obj
+CHECKIDX: ?Add at MyMathFuncs@MathFuncs@@SANNN at Z in Debug\mymath.obj
+CHECKIDX: ?Divide at MyMathFuncs@MathFuncs@@SANNN at Z in Debug\mymath.obj
+CHECKIDX: ?Multiply at MyMathFuncs@MathFuncs@@SANNN at Z in Debug\mymath.obj
+CHECKIDX: ?Subtract at MyMathFuncs@MathFuncs@@SANNN at Z in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at C@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at D@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at E@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at F@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at G@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at H@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at I@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at J@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at K@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at M@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at N@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at O@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at _J@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at _K@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?_Rank@?$_Arithmetic_traits at _N@std@@2HB in Debug\mymath.obj
+CHECKIDX: ?value@?$integral_constant at I$0A@@tr1 at std@@2IB in Debug\mymath.obj
+CHECKIDX: ?value@?$integral_constant at _N$00 at tr1@std@@2_NB in Debug\mymath.obj
+CHECKIDX: ?value@?$integral_constant at _N$0A@@tr1 at std@@2_NB in Debug\mymath.obj
+CHECKIDX: __CT??_R0PAVexception at std@@@84 in Debug\mymath.obj
+CHECKIDX: __CT??_R0PAVinvalid_argument at std@@@84 in Debug\mymath.obj
+CHECKIDX: __CT??_R0PAVlogic_error at std@@@84 in Debug\mymath.obj
+CHECKIDX: __CT??_R0PAX at 84 in Debug\mymath.obj
+CHECKIDX: __CTA4PAVinvalid_argument at std@@ in Debug\mymath.obj
+CHECKIDX: __TI4PAVinvalid_argument at std@@ in Debug\mymath.obj
+CHECKIDX: __real at 0000000000000000 in Debug\mymath.obj
+CHECKIDX: Debug\stdafx.obj:
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$T
+CHECKIDX: 00000000 i .drectve
+CHECKIDX: 00ab9d1b a @comp.id
+CHECKIDX: 00000001 a @feat.00
+CHECKIDX: Debug\mymath.obj:
+CHECKIDX: 00000000 d .data
+CHECKIDX: 00000000 d .data
+CHECKIDX: 00000000 d .data
+CHECKIDX: 00000000 d .data
+CHECKIDX: 00000000 d .data
+CHECKIDX: 00000000 d .data
+CHECKIDX: 00000000 d .data
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$S
+CHECKIDX: 00000000 N .debug$T
+CHECKIDX: 00000000 i .drectve
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rdata$r
+CHECKIDX: 00000000 r .rtc$IMZ
+CHECKIDX: 00000000 r .rtc$TMZ
+CHECKIDX: 00000000 N .sxdata
+CHECKIDX: 00000000 t .text
+CHECKIDX: 00000000 t .text
+CHECKIDX: 00000000 t .text
+CHECKIDX: 00000000 t .text
+CHECKIDX: 00000000 t .text
+CHECKIDX: 00000000 t .text
+CHECKIDX: 00000000 t .text
+CHECKIDX: 00000000 t .text
+CHECKIDX: 00000000 t .text
+CHECKIDX: 00000000 t .text
+CHECKIDX: 00000000 t .text$x
+CHECKIDX: 00000000 r .xdata$x
+CHECKIDX: 00000000 r .xdata$x
+CHECKIDX: 00000000 r .xdata$x
+CHECKIDX: 00000000 r .xdata$x
+CHECKIDX: 00000000 r .xdata$x
+CHECKIDX: 00000000 r .xdata$x
+CHECKIDX: 00000000 r .xdata$x
+CHECKIDX: 00000000 T ??0invalid_argument at std@@QAE at PBD@Z
+CHECKIDX: 00000000 T ??0logic_error at std@@QAE at PBD@Z
+CHECKIDX: 00000000 T ??1invalid_argument at std@@UAE at XZ
+CHECKIDX: 00000000 T ??1logic_error at std@@UAE at XZ
+CHECKIDX: U ??2 at YAPAXI@Z
+CHECKIDX: U ??3 at YAXPAX@Z
+CHECKIDX: 00000004 R ??_7invalid_argument at std@@6B@
+CHECKIDX: 00000004 R ??_7logic_error at std@@6B@
+CHECKIDX: U ??_7type_info@@6B@
+CHECKIDX: 00000000 R ??_C at _0BC@IHENMCGI at b?5cannot?5be?5zero?$CB?$AA@
+CHECKIDX: w ??_Einvalid_argument at std@@UAEPAXI at Z
+CHECKIDX: w ??_Elogic_error at std@@UAEPAXI at Z
+CHECKIDX: U ??_Ginvalid_argument at std@@UAEPAXI at Z
+CHECKIDX: 00000000 T ??_Ginvalid_argument at std@@UAEPAXI at Z
+CHECKIDX: 00000000 T ??_Glogic_error at std@@UAEPAXI at Z
+CHECKIDX: U ??_Glogic_error at std@@UAEPAXI at Z
+CHECKIDX: 00000000 D ??_R0?AVexception at std@@@8
+CHECKIDX: 00000000 D ??_R0?AVinvalid_argument at std@@@8
+CHECKIDX: 00000000 D ??_R0?AVlogic_error at std@@@8
+CHECKIDX: 00000000 D ??_R0PAVexception at std@@@8
+CHECKIDX: 00000000 D ??_R0PAVinvalid_argument at std@@@8
+CHECKIDX: 00000000 D ??_R0PAVlogic_error at std@@@8
+CHECKIDX: 00000000 D ??_R0PAX at 8
+CHECKIDX: 00000000 R ??_R1A@?0A at EA@exception at std@@8
+CHECKIDX: 00000000 R ??_R1A@?0A at EA@invalid_argument at std@@8
+CHECKIDX: 00000000 R ??_R1A@?0A at EA@logic_error at std@@8
+CHECKIDX: 00000000 R ??_R2exception at std@@8
+CHECKIDX: 00000000 R ??_R2invalid_argument at std@@8
+CHECKIDX: 00000000 R ??_R2logic_error at std@@8
+CHECKIDX: 00000000 R ??_R3exception at std@@8
+CHECKIDX: 00000000 R ??_R3invalid_argument at std@@8
+CHECKIDX: 00000000 R ??_R3logic_error at std@@8
+CHECKIDX: 00000000 R ??_R4invalid_argument at std@@6B@
+CHECKIDX: 00000000 R ??_R4logic_error at std@@6B@
+CHECKIDX: 00000000 T ?Add at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: 00000000 T ?Divide at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: 00000000 T ?Multiply at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: 00000000 T ?Subtract at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at C@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at D@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at E@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at F@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at G@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at H@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at I@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at J@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at K@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at M@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at N@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at O@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at _J@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at _K@std@@2HB
+CHECKIDX: 00000000 R ?_Rank@?$_Arithmetic_traits at _N@std@@2HB
+CHECKIDX: 00000000 R ?value@?$integral_constant at I$0A@@tr1 at std@@2IB
+CHECKIDX: 00000000 R ?value@?$integral_constant at _N$00 at tr1@std@@2_NB
+CHECKIDX: 00000000 R ?value@?$integral_constant at _N$0A@@tr1 at std@@2_NB
+CHECKIDX: U ?what at exception@std@@UBEPBDXZ
+CHECKIDX: U @__security_check_cookie at 4
+CHECKIDX: 00ab9d1b a @comp.id
+CHECKIDX: 00000001 a @feat.00
+CHECKIDX: 00000000 R __CT??_R0PAVexception at std@@@84
+CHECKIDX: 00000000 R __CT??_R0PAVinvalid_argument at std@@@84
+CHECKIDX: 00000000 R __CT??_R0PAVlogic_error at std@@@84
+CHECKIDX: 00000000 R __CT??_R0PAX at 84
+CHECKIDX: 00000000 R __CTA4PAVinvalid_argument at std@@
+CHECKIDX: U __CxxThrowException at 8
+CHECKIDX: U __RTC_CheckEsp
+CHECKIDX: U __RTC_InitBase
+CHECKIDX: 00000000 r __RTC_InitBase.rtc$IMZ
+CHECKIDX: U __RTC_Shutdown
+CHECKIDX: 00000000 r __RTC_Shutdown.rtc$TMZ
+CHECKIDX: 00000000 R __TI4PAVinvalid_argument at std@@
+CHECKIDX: U ___CxxFrameHandler3
+CHECKIDX: U ___security_cookie
+CHECKIDX: 00000008 r __ehfuncinfo$?Divide at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: 0000000e t __ehhandler$?Divide at MyMathFuncs@MathFuncs@@SANNN at Z
+CHECKIDX: U __fltused
+CHECKIDX: U __imp_??0exception at std@@QAE at ABQBD@Z
+CHECKIDX: U __imp_??1exception at std@@UAE at XZ
+CHECKIDX: 00000000 R __real at 0000000000000000
+CHECKIDX: 00000000 t __unwindfunclet$?Divide at MyMathFuncs@MathFuncs@@SANNN at Z$0
+CHECKIDX: 00000000 r __unwindtable$?Divide at MyMathFuncs@MathFuncs@@SANNN at Z
Index: include/llvm/Object/Archive.h
===================================================================
--- include/llvm/Object/Archive.h (revision 167054)
+++ include/llvm/Object/Archive.h (working copy)
@@ -122,6 +122,16 @@
Archive(MemoryBuffer *source, error_code &ec);
+ enum Kind {
+ K_GNU,
+ K_BSD,
+ K_COFF
+ };
+
+ Kind kind() const {
+ return Format;
+ }
+
child_iterator begin_children(bool skip_internal = true) const;
child_iterator end_children() const;
@@ -133,9 +143,13 @@
return v->isArchive();
}
+ // check if a symbol is in the archive
+ error_code findSym(StringRef name, child_iterator &c) const;
+
private:
child_iterator SymbolTable;
child_iterator StringTable;
+ Kind Format;
};
}
Index: tools/llvm-nm/llvm-nm.cpp
===================================================================
--- tools/llvm-nm/llvm-nm.cpp (revision 167054)
+++ tools/llvm-nm/llvm-nm.cpp (working copy)
@@ -113,6 +113,10 @@
cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden,
cl::desc("Exclude aliases from output"));
+ cl::opt<bool> ArchiveMap("print-armap",
+ cl::desc("Print the archive map"));
+ cl::alias ArchiveMaps("s", cl::desc("Alias for --print-armap"),
+ cl::aliasopt(ArchiveMap));
bool PrintAddress = true;
bool MultipleFiles = false;
@@ -346,6 +350,24 @@
return;
if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) {
+ if (ArchiveMap) {
+ outs() << "Archive map" << "\n";
+ for (object::Archive::symbol_iterator i = a->begin_symbols(),
+ e = a->end_symbols(); i != e; ++i) {
+ object::Archive::child_iterator c;
+ StringRef symname;
+ StringRef filename;
+ if (error(i->getMember(c)))
+ return;
+ if (error(i->getName(symname)))
+ return;
+ if (error(c->getName(filename)))
+ return;
+ outs() << symname << " in " << filename << "\n";
+ }
+ outs() << "\n";
+ }
+
for (object::Archive::child_iterator i = a->begin_children(),
e = a->end_children(); i != e; ++i) {
OwningPtr<Binary> child;
Index: lib/Object/Archive.cpp
===================================================================
--- lib/Object/Archive.cpp (revision 167054)
+++ lib/Object/Archive.cpp (working copy)
@@ -122,7 +122,15 @@
+ sizeof(ArchiveMemberHeader)
+ Parent->StringTable->getSize()))
return object_error::parse_failed;
+
+ // The filename would exist in the StringTable only if the filename
+ // is a long filename. The filename be terminated by a /
+ if (Parent->kind() == K_GNU) {
+ StringRef::size_type end = StringRef(addr).find('/');
+ Result = StringRef(addr, end);
+ } else {
Result = addr;
+ }
return object_error::success;
} else if (name.startswith("#1/")) {
APInt name_size;
@@ -187,7 +195,40 @@
child_iterator i = begin_children(false);
child_iterator e = end_children();
- if (i != e) ++i; // Nobody cares about the first member.
+ StringRef name;
+ if ((ec = i->getName(name)))
+ return;
+
+ // Below is the pattern that is used to figure out the archive format
+ // GNU archive format
+ // First member : / (points to the symbol table )
+ // Second member : // (may exist, if it exists, points to the string table)
+ // Note : The string table is used if the filename exceeds 15 characters
+ // BSD archive format
+ // First member : __.SYMDEF (points to the symbol table)
+ // There is no string table, if the filename exceeds 15 characters or has a
+ // embedded space, the filename has #1/<size>, The size represents the size
+ // of the filename that needs to be read after the archive header
+ // COFF archive format
+ // First member : /
+ // Second member : / (provides a directory of symbols)
+ // Third member : // contains the string table, this is present even if the
+ // string table is empty
+ if (name == "/") {
+ SymbolTable = i;
+ StringTable = e;
+ if (i != e) ++i;
+ if ((ec = i->getName(name)))
+ return;
+ const char *data = name.data();
+ if (data[0] != '/') {
+ Format = K_GNU;
+ } else if (data[1] == '/') {
+ Format = K_GNU;
+ StringTable = i;
+ ++i;
+ } else {
+ Format = K_COFF;
if (i != e) {
SymbolTable = i;
++i;
@@ -195,7 +236,12 @@
if (i != e) {
StringTable = i;
}
-
+ }
+ } else if (name == "__.SYMDEF") {
+ Format = K_BSD;
+ SymbolTable = i;
+ StringTable = e;
+ }
ec = object_error::success;
}
@@ -222,17 +268,28 @@
error_code Archive::Symbol::getMember(child_iterator &Result) const {
const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart();
- uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
const char *offsets = buf + 4;
+ uint32_t offset = 0;
+ if (Parent->kind() == K_GNU) {
+ offset = *(reinterpret_cast<const support::ubig32_t*>(offsets)
+ + SymbolIndex);
+ } else if (Parent->kind() == K_BSD) {
+ assert("BSD format is not supported");
+ } else {
+ uint32_t member_count = 0;
+ member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
buf += 4 + (member_count * 4); // Skip offsets.
const char *indicies = buf + 4;
-
uint16_t offsetindex =
*(reinterpret_cast<const support::ulittle16_t*>(indicies)
+ SymbolIndex);
-
- uint32_t offset = *(reinterpret_cast<const support::ulittle32_t*>(offsets)
+ uint32_t *offsetaddr =
+ (uint32_t *)(reinterpret_cast<const support::ulittle32_t*>(offsets)
+ (offsetindex - 1));
+ assert((const char *)offsetaddr <
+ Parent->SymbolTable->getBuffer()->getBufferEnd());
+ offset = *(offsetaddr);
+ }
const char *Loc = Parent->getData().begin() + offset;
size_t Size = sizeof(ArchiveMemberHeader) +
@@ -253,10 +310,20 @@
Archive::symbol_iterator Archive::begin_symbols() const {
const char *buf = SymbolTable->getBuffer()->getBufferStart();
- uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+ if (kind() == K_GNU) {
+ uint32_t symbol_count = 0;
+ symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf);
+ buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
+ } else if (kind() == K_BSD) {
+ assert("BSD archive format is not supported");
+ } else {
+ uint32_t member_count = 0;
+ uint32_t symbol_count = 0;
+ member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
buf += 4 + (member_count * 4); // Skip offsets.
- uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+ symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
buf += 4 + (symbol_count * 2); // Skip indices.
+ }
uint32_t string_start_offset =
buf - SymbolTable->getBuffer()->getBufferStart();
return symbol_iterator(Symbol(this, 0, string_start_offset));
@@ -264,9 +331,37 @@
Archive::symbol_iterator Archive::end_symbols() const {
const char *buf = SymbolTable->getBuffer()->getBufferStart();
- uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+ uint32_t symbol_count = 0;
+ if (kind() == K_GNU) {
+ symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf);
+ buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
+ } else if (kind() == K_BSD) {
+ assert("BSD archive format is not supported");
+ } else {
+ uint32_t member_count = 0;
+ member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
buf += 4 + (member_count * 4); // Skip offsets.
- uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+ symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+ }
return symbol_iterator(
Symbol(this, symbol_count, 0));
}
+
+error_code Archive::findSym(StringRef name, child_iterator &result) const {
+ error_code ec;
+ StringRef symname;
+ Archive::symbol_iterator bs = begin_symbols();
+ Archive::symbol_iterator es = end_symbols();
+
+ for (; bs != es; ++bs)
+ {
+ if ((ec = bs->getName(symname)))
+ return ec;
+ if (symname == name) {
+ if ((ec = bs->getMember(result)))
+ return ec;
+ return error_code::success();
+ }
+ }
+ return object_error::parse_failed;
+}
More information about the llvm-commits
mailing list