From 91f86b7e1c07e73667537e6b849f9977caeeed3d Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 21 Feb 2014 20:10:59 +0000 Subject: Add a SymbolicFile interface between Binary and ObjectFile. This interface allows IRObjectFile to be implemented without having dummy methods for all section and segment related methods. Both llvm-ar and llvm-nm are changed to use it. Unfortunately the mangler is still not plugged in since it requires some refactoring to make a Module hold a DataLayout. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201881 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/Archive.h | 3 +- include/llvm/Object/Binary.h | 15 ++- include/llvm/Object/COFF.h | 4 +- include/llvm/Object/ELFObjectFile.h | 12 +-- include/llvm/Object/IRObjectFile.h | 44 +++++++++ include/llvm/Object/MachO.h | 4 +- include/llvm/Object/ObjectFile.h | 163 ++++++++++--------------------- include/llvm/Object/SymbolicFile.h | 190 ++++++++++++++++++++++++++++++++++++ lib/Object/Archive.cpp | 5 +- lib/Object/Binary.cpp | 10 +- lib/Object/CMakeLists.txt | 2 + lib/Object/COFFObjectFile.cpp | 12 +-- lib/Object/IRObjectFile.cpp | 139 ++++++++++++++++++++++++++ lib/Object/LLVMBuild.txt | 2 +- lib/Object/MachOObjectFile.cpp | 12 +-- lib/Object/ObjectFile.cpp | 11 ++- lib/Object/SymbolicFile.cpp | 67 +++++++++++++ test/Object/nm-ir.ll | 34 +++++++ tools/llvm-ar/llvm-ar.cpp | 42 ++++---- tools/llvm-nm/CMakeLists.txt | 2 - tools/llvm-nm/llvm-nm.cpp | 184 ++++++++++++++-------------------- 21 files changed, 676 insertions(+), 281 deletions(-) create mode 100644 include/llvm/Object/IRObjectFile.h create mode 100644 include/llvm/Object/SymbolicFile.h create mode 100644 lib/Object/IRObjectFile.cpp create mode 100644 lib/Object/SymbolicFile.cpp create mode 100644 test/Object/nm-ir.ll diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index ce9391e8f0..2ba7bf23ac 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -92,7 +92,8 @@ public: error_code getMemoryBuffer(OwningPtr &Result, bool FullPath = false) const; - error_code getAsBinary(OwningPtr &Result) const; + error_code getAsBinary(OwningPtr &Result, + LLVMContext *Context = 0) const; }; class child_iterator { diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 420cc9bba8..b10e40adf7 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -20,6 +20,7 @@ namespace llvm { +class LLVMContext; class MemoryBuffer; class StringRef; @@ -41,6 +42,8 @@ protected: enum { ID_Archive, ID_MachOUniversalBinary, + ID_IR, // LLVM IR + // Object and children. ID_StartObjects, ID_COFF, @@ -86,6 +89,10 @@ public: return TypeID > ID_StartObjects && TypeID < ID_EndObjects; } + bool isSymbolic() const { + return isIR() || isObject(); + } + bool isArchive() const { return TypeID == ID_Archive; } @@ -106,6 +113,10 @@ public: return TypeID == ID_COFF; } + bool isIR() const { + return TypeID == ID_IR; + } + bool isLittleEndian() const { return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || TypeID == ID_MachO32B || TypeID == ID_MachO64B); @@ -117,9 +128,7 @@ public: /// @param Source The data to create the Binary from. Ownership is transferred /// to the Binary if successful. If an error is returned, /// Source is destroyed by createBinary before returning. -ErrorOr createBinary(MemoryBuffer *Source, - sys::fs::file_magic Type = - sys::fs::file_magic::unknown); +ErrorOr createBinary(MemoryBuffer *Source, LLVMContext *Context = 0); ErrorOr createBinary(StringRef Path); } diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index d38ed2e096..dfcff2b411 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -355,8 +355,8 @@ protected: public: COFFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); - symbol_iterator symbol_begin() const LLVM_OVERRIDE; - symbol_iterator symbol_end() const LLVM_OVERRIDE; + basic_symbol_iterator symbol_begin_impl() const LLVM_OVERRIDE; + basic_symbol_iterator symbol_end_impl() const LLVM_OVERRIDE; library_iterator needed_library_begin() const LLVM_OVERRIDE; library_iterator needed_library_end() const LLVM_OVERRIDE; section_iterator section_begin() const LLVM_OVERRIDE; diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index cadf920c27..ae6b6068d5 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -180,8 +180,8 @@ public: const Elf_Sym *getSymbol(DataRefImpl Symb) const; - symbol_iterator symbol_begin() const LLVM_OVERRIDE; - symbol_iterator symbol_end() const LLVM_OVERRIDE; + basic_symbol_iterator symbol_begin_impl() const LLVM_OVERRIDE; + basic_symbol_iterator symbol_end_impl() const LLVM_OVERRIDE; symbol_iterator dynamic_symbol_begin() const; symbol_iterator dynamic_symbol_end() const; @@ -824,13 +824,13 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec, EF(Object, ec) {} template -symbol_iterator ELFObjectFile::symbol_begin() const { - return symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); +basic_symbol_iterator ELFObjectFile::symbol_begin_impl() const { + return basic_symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); } template -symbol_iterator ELFObjectFile::symbol_end() const { - return symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); +basic_symbol_iterator ELFObjectFile::symbol_end_impl() const { + return basic_symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); } template diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h new file mode 100644 index 0000000000..e1effa6745 --- /dev/null +++ b/include/llvm/Object/IRObjectFile.h @@ -0,0 +1,44 @@ +//===- IRObjectFile.h - LLVM IR object file implementation ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the IRObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_IR_OBJECT_FILE_H +#define LLVM_OBJECT_IR_OBJECT_FILE_H + +#include "llvm/Object/SymbolicFile.h" + +namespace llvm { +class Module; +class GlobalValue; + +namespace object { +class IRObjectFile : public SymbolicFile { + OwningPtr M; +public: + IRObjectFile(MemoryBuffer *Object, error_code &EC, LLVMContext &Context, + bool BufferOwned); + void moveSymbolNext(DataRefImpl &Symb) const LLVM_OVERRIDE; + error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const + LLVM_OVERRIDE; + uint32_t getSymbolFlags(DataRefImpl Symb) const LLVM_OVERRIDE; + const GlobalValue &getSymbolGV(DataRefImpl Symb) const; + basic_symbol_iterator symbol_begin_impl() const LLVM_OVERRIDE; + basic_symbol_iterator symbol_end_impl() const LLVM_OVERRIDE; + + static inline bool classof(const Binary *v) { + return v->isIR(); + } +}; +} +} + +#endif diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 50cdfc3839..4d6ef6d9a6 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -126,8 +126,8 @@ public: // TODO: Would be useful to have an iterator based version // of the load command interface too. - symbol_iterator symbol_begin() const LLVM_OVERRIDE; - symbol_iterator symbol_end() const LLVM_OVERRIDE; + basic_symbol_iterator symbol_begin_impl() const LLVM_OVERRIDE; + basic_symbol_iterator symbol_end_impl() const LLVM_OVERRIDE; section_iterator section_begin() const LLVM_OVERRIDE; section_iterator section_end() const LLVM_OVERRIDE; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 786f803187..cb1c04688d 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -15,7 +15,7 @@ #define LLVM_OBJECT_OBJECTFILE_H #include "llvm/ADT/StringRef.h" -#include "llvm/Object/Binary.h" +#include "llvm/Object/SymbolicFile.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" @@ -28,61 +28,8 @@ namespace object { class ObjectFile; -union DataRefImpl { - // This entire union should probably be a - // char[max(8, sizeof(uintptr_t))] and require the impl to cast. - struct { - uint32_t a, b; - } d; - uintptr_t p; - DataRefImpl() { - std::memset(this, 0, sizeof(DataRefImpl)); - } -}; - -template -class content_iterator { - content_type Current; -public: - content_iterator(content_type symb) - : Current(symb) {} - - const content_type* operator->() const { - return &Current; - } - - const content_type &operator*() const { - return Current; - } - - bool operator==(const content_iterator &other) const { - return Current == other.Current; - } - - bool operator!=(const content_iterator &other) const { - return !(*this == other); - } - - content_iterator &operator++() { // preincrement - Current.moveNext(); - return *this; - } -}; - -inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { - // Check bitwise identical. This is the only legal way to compare a union w/o - // knowing which member is in use. - return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; -} - -inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { - // Check bitwise identical. This is the only legal way to compare a union w/o - // knowing which member is in use. - return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; -} - class SymbolRef; -typedef content_iterator symbol_iterator; +class symbol_iterator; /// RelocationRef - This is a value type class that represents a single /// relocation in the list of relocations in the object file. @@ -172,13 +119,11 @@ public: /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. -class SymbolRef { +class SymbolRef : public BasicSymbolRef { friend class SectionRef; - DataRefImpl SymbolPimpl; - const ObjectFile *OwningObject; public: - SymbolRef() : OwningObject(NULL) { } + SymbolRef() : BasicSymbolRef() {} enum Type { ST_Unknown, // Type not specified @@ -189,24 +134,8 @@ public: ST_Other }; - enum Flags LLVM_ENUM_INT_TYPE(unsigned) { - SF_None = 0, - SF_Undefined = 1U << 0, // Symbol is defined in another object file - SF_Global = 1U << 1, // Global symbol - SF_Weak = 1U << 2, // Weak symbol - SF_Absolute = 1U << 3, // Absolute symbol - SF_Common = 1U << 4, // Symbol has common linkage - SF_FormatSpecific = 1U << 5 // Specific to the object file format - // (e.g. section symbols) - }; - SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); - bool operator==(const SymbolRef &Other) const; - bool operator<(const SymbolRef &Other) const; - - void moveNext(); - error_code getName(StringRef &Result) const; /// Returns the symbol virtual address (i.e. address at which it will be /// mapped). @@ -217,9 +146,6 @@ public: error_code getSize(uint64_t &Result) const; error_code getType(SymbolRef::Type &Result) const; - /// Get symbol flags (bitwise OR of SymbolRef::Flags) - uint32_t getFlags() const; - /// @brief Get section this symbol is defined in reference to. Result is /// end_sections() if it is undefined or is an absolute symbol. error_code getSection(section_iterator &Result) const; @@ -227,7 +153,25 @@ public: /// @brief Get value of the symbol in the symbol table. error_code getValue(uint64_t &Val) const; - DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObject() const; +}; + +class symbol_iterator : public basic_symbol_iterator { +public: + symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {} + symbol_iterator(const basic_symbol_iterator &B) + : basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(), + cast(B->getObject()))) {} + + const SymbolRef *operator->() const { + const BasicSymbolRef &P = basic_symbol_iterator::operator *(); + return static_cast(&P); + } + + const SymbolRef &operator*() const { + const BasicSymbolRef &P = basic_symbol_iterator::operator *(); + return static_cast(P); + } }; /// LibraryRef - This is a value type class that represents a single library in @@ -254,12 +198,10 @@ public: }; typedef content_iterator library_iterator; -const uint64_t UnknownAddressOrSize = ~0ULL; - /// ObjectFile - This class is the base class for all object file types. /// Concrete instances of this object are created by createObjectFile, which /// figures out which type to create. -class ObjectFile : public Binary { +class ObjectFile : public SymbolicFile { virtual void anchor(); ObjectFile() LLVM_DELETED_FUNCTION; ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; @@ -280,15 +222,14 @@ protected: // Implementations assume that the DataRefImpl is valid and has not been // modified externally. It's UB otherwise. friend class SymbolRef; - virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; + virtual error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res)const=0; virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const = 0; - virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const = 0; virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const = 0; @@ -342,8 +283,8 @@ protected: public: - virtual symbol_iterator symbol_begin() const = 0; - virtual symbol_iterator symbol_end() const = 0; + symbol_iterator begin_symbols() const; + symbol_iterator end_symbols() const; virtual section_iterator section_begin() const = 0; virtual section_iterator section_end() const = 0; @@ -391,59 +332,57 @@ public: // Inline function definitions. inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) - : SymbolPimpl(SymbolP) - , OwningObject(Owner) {} - -inline bool SymbolRef::operator==(const SymbolRef &Other) const { - return SymbolPimpl == Other.SymbolPimpl; -} + : BasicSymbolRef(SymbolP, Owner) {} -inline bool SymbolRef::operator<(const SymbolRef &Other) const { - return SymbolPimpl < Other.SymbolPimpl; +inline symbol_iterator ObjectFile::begin_symbols() const { + basic_symbol_iterator I = symbol_begin_impl(); + const BasicSymbolRef &Ref = *I; + const SymbolRef &Cast = static_cast(Ref); + return symbol_iterator(Cast); } -inline void SymbolRef::moveNext() { - return OwningObject->moveSymbolNext(SymbolPimpl); +inline symbol_iterator ObjectFile::end_symbols() const { + basic_symbol_iterator I = symbol_end_impl(); + const BasicSymbolRef &Ref = *I; + const SymbolRef &Cast = static_cast(Ref); + return symbol_iterator(Cast); } inline error_code SymbolRef::getName(StringRef &Result) const { - return OwningObject->getSymbolName(SymbolPimpl, Result); + return getObject()->getSymbolName(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getAddress(uint64_t &Result) const { - return OwningObject->getSymbolAddress(SymbolPimpl, Result); + return getObject()->getSymbolAddress(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getFileOffset(uint64_t &Result) const { - return OwningObject->getSymbolFileOffset(SymbolPimpl, Result); + return getObject()->getSymbolFileOffset(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getAlignment(uint32_t &Result) const { - return OwningObject->getSymbolAlignment(SymbolPimpl, Result); + return getObject()->getSymbolAlignment(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getSize(uint64_t &Result) const { - return OwningObject->getSymbolSize(SymbolPimpl, Result); -} - -inline uint32_t SymbolRef::getFlags() const { - return OwningObject->getSymbolFlags(SymbolPimpl); + return getObject()->getSymbolSize(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getSection(section_iterator &Result) const { - return OwningObject->getSymbolSection(SymbolPimpl, Result); + return getObject()->getSymbolSection(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getType(SymbolRef::Type &Result) const { - return OwningObject->getSymbolType(SymbolPimpl, Result); + return getObject()->getSymbolType(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getValue(uint64_t &Val) const { - return OwningObject->getSymbolValue(SymbolPimpl, Val); + return getObject()->getSymbolValue(getRawDataRefImpl(), Val); } -inline DataRefImpl SymbolRef::getRawDataRefImpl() const { - return SymbolPimpl; +inline const ObjectFile *SymbolRef::getObject() const { + const SymbolicFile *O = BasicSymbolRef::getObject(); + return cast(O); } @@ -514,8 +453,8 @@ inline error_code SectionRef::isReadOnlyData(bool &Result) const { } inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { - return OwningObject->sectionContainsSymbol(SectionPimpl, S.SymbolPimpl, - Result); + return OwningObject->sectionContainsSymbol(SectionPimpl, + S.getRawDataRefImpl(), Result); } inline relocation_iterator SectionRef::relocation_begin() const { diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h new file mode 100644 index 0000000000..69f128d2bc --- /dev/null +++ b/include/llvm/Object/SymbolicFile.h @@ -0,0 +1,190 @@ +//===- SymbolicFile.h - Interface that only provides symbols ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SymbolicFile interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_SYMBOLIC_FILE_H +#define LLVM_OBJECT_SYMBOLIC_FILE_H + +#include "llvm/Object/Binary.h" + +namespace llvm { +namespace object { + +union DataRefImpl { + // This entire union should probably be a + // char[max(8, sizeof(uintptr_t))] and require the impl to cast. + struct { + uint32_t a, b; + } d; + uintptr_t p; + DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); } +}; + +inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; +} + +inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; +} + +template class content_iterator { + content_type Current; + +public: + content_iterator(content_type symb) : Current(symb) {} + + const content_type *operator->() const { return &Current; } + + const content_type &operator*() const { return Current; } + + bool operator==(const content_iterator &other) const { + return Current == other.Current; + } + + bool operator!=(const content_iterator &other) const { + return !(*this == other); + } + + content_iterator &operator++() { // preincrement + Current.moveNext(); + return *this; + } +}; + +class SymbolicFile; + +/// This is a value type class that represents a single symbol in the list of +/// symbols in the object file. +class BasicSymbolRef { + DataRefImpl SymbolPimpl; + const SymbolicFile *OwningObject; + +public: + // FIXME: should we add a SF_Text? + enum Flags LLVM_ENUM_INT_TYPE(unsigned) { + SF_None = 0, + SF_Undefined = 1U << 0, // Symbol is defined in another object file + SF_Global = 1U << 1, // Global symbol + SF_Weak = 1U << 2, // Weak symbol + SF_Absolute = 1U << 3, // Absolute symbol + SF_Common = 1U << 4, // Symbol has common linkage + SF_FormatSpecific = 1U << 5 // Specific to the object file format + // (e.g. section symbols) + }; + + BasicSymbolRef() : OwningObject(NULL) { } + BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner); + + bool operator==(const BasicSymbolRef &Other) const; + bool operator<(const BasicSymbolRef &Other) const; + + void moveNext(); + + error_code printName(raw_ostream &OS) const; + + /// Get symbol flags (bitwise OR of SymbolRef::Flags) + uint32_t getFlags() const; + + DataRefImpl getRawDataRefImpl() const; + const SymbolicFile *getObject() const; +}; + +typedef content_iterator basic_symbol_iterator; + +const uint64_t UnknownAddressOrSize = ~0ULL; + +class SymbolicFile : public Binary { +public: + virtual ~SymbolicFile(); + SymbolicFile(unsigned int Type, MemoryBuffer *Source, bool BufferOwned); + + // virtual interface. + virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; + + virtual error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const = 0; + + virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0; + + virtual basic_symbol_iterator symbol_begin_impl() const = 0; + + virtual basic_symbol_iterator symbol_end_impl() const = 0; + + // convenience wrappers. + basic_symbol_iterator symbol_begin() const { + return symbol_begin_impl(); + } + basic_symbol_iterator symbol_end() const { + return symbol_end_impl(); + } + + // construction aux. + static ErrorOr createIRObjectFile(MemoryBuffer *Object, + LLVMContext &Context, + bool BufferOwned = true); + + static ErrorOr createSymbolicFile(MemoryBuffer *Object, + bool BufferOwned, + sys::fs::file_magic Type, + LLVMContext *Context); + + static ErrorOr createSymbolicFile(MemoryBuffer *Object) { + return createSymbolicFile(Object, true, sys::fs::file_magic::unknown, 0); + } + static ErrorOr createSymbolicFile(StringRef ObjectPath); + + static inline bool classof(const Binary *v) { + return v->isSymbolic(); + } +}; + +inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP, + const SymbolicFile *Owner) + : SymbolPimpl(SymbolP), OwningObject(Owner) {} + +inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const { + return SymbolPimpl == Other.SymbolPimpl; +} + +inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const { + return SymbolPimpl < Other.SymbolPimpl; +} + +inline void BasicSymbolRef::moveNext() { + return OwningObject->moveSymbolNext(SymbolPimpl); +} + +inline error_code BasicSymbolRef::printName(raw_ostream &OS) const { + return OwningObject->printSymbolName(OS, SymbolPimpl); +} + +inline uint32_t BasicSymbolRef::getFlags() const { + return OwningObject->getSymbolFlags(SymbolPimpl); +} + +inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const { + return SymbolPimpl; +} + +inline const SymbolicFile *BasicSymbolRef::getObject() const { + return OwningObject; +} + +} +} + +#endif diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 286e9eebab..99bc4a5a3b 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -182,12 +182,13 @@ error_code Archive::Child::getMemoryBuffer(OwningPtr &Result, return error_code::success(); } -error_code Archive::Child::getAsBinary(OwningPtr &Result) const { +error_code Archive::Child::getAsBinary(OwningPtr &Result, + LLVMContext *Context) const { OwningPtr ret; OwningPtr Buff; if (error_code ec = getMemoryBuffer(Buff)) return ec; - ErrorOr BinaryOrErr = createBinary(Buff.take()); + ErrorOr BinaryOrErr = createBinary(Buff.take(), Context); if (error_code EC = BinaryOrErr.getError()) return EC; Result.reset(BinaryOrErr.get()); diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp index 63898d277f..c7f868fcdd 100644 --- a/lib/Object/Binary.cpp +++ b/lib/Object/Binary.cpp @@ -42,10 +42,9 @@ StringRef Binary::getFileName() const { } ErrorOr object::createBinary(MemoryBuffer *Source, - sys::fs::file_magic Type) { + LLVMContext *Context) { OwningPtr scopedSource(Source); - if (Type == sys::fs::file_magic::unknown) - Type = sys::fs::identify_magic(Source->getBuffer()); + sys::fs::file_magic Type = sys::fs::identify_magic(Source->getBuffer()); switch (Type) { case sys::fs::file_magic::archive: @@ -67,11 +66,12 @@ ErrorOr object::createBinary(MemoryBuffer *Source, case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: - return ObjectFile::createObjectFile(scopedSource.take(), true, Type); + case sys::fs::file_magic::bitcode: + return ObjectFile::createSymbolicFile(scopedSource.take(), true, Type, + Context); case sys::fs::file_magic::macho_universal_binary: return MachOUniversalBinary::create(scopedSource.take()); case sys::fs::file_magic::unknown: - case sys::fs::file_magic::bitcode: case sys::fs::file_magic::windows_resource: // Unrecognized object file format. return object_error::invalid_file_type; diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt index 1f07cbba77..dc182966ae 100644 --- a/lib/Object/CMakeLists.txt +++ b/lib/Object/CMakeLists.txt @@ -7,9 +7,11 @@ add_llvm_library(LLVMObject ELFObjectFile.cpp ELFYAML.cpp Error.cpp + IRObjectFile.cpp MachOObjectFile.cpp MachOUniversal.cpp Object.cpp ObjectFile.cpp + SymbolicFile.cpp YAML.cpp ) diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 5dcb174986..ed5494dc39 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -549,17 +549,17 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC, EC = object_error::success; } -symbol_iterator COFFObjectFile::symbol_begin() const { +basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { DataRefImpl Ret; Ret.p = reinterpret_cast(SymbolTable); - return symbol_iterator(SymbolRef(Ret, this)); + return basic_symbol_iterator(SymbolRef(Ret, this)); } -symbol_iterator COFFObjectFile::symbol_end() const { +basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { // The symbol table ends where the string table begins. DataRefImpl Ret; Ret.p = reinterpret_cast(StringTable); - return symbol_iterator(SymbolRef(Ret, this)); + return basic_symbol_iterator(SymbolRef(Ret, this)); } library_iterator COFFObjectFile::needed_library_begin() const { @@ -832,8 +832,8 @@ const coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const { return toSymb(It->getRawDataRefImpl()); } -const coff_relocation *COFFObjectFile::getCOFFRelocation( - relocation_iterator &It) const { +const coff_relocation * +COFFObjectFile::getCOFFRelocation(relocation_iterator &It) const { return toRel(It->getRawDataRefImpl()); } diff --git a/lib/Object/IRObjectFile.cpp b/lib/Object/IRObjectFile.cpp new file mode 100644 index 0000000000..fb511ca28f --- /dev/null +++ b/lib/Object/IRObjectFile.cpp @@ -0,0 +1,139 @@ +//===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Part of the IRObjectFile class implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Object/IRObjectFile.h" +using namespace llvm; +using namespace object; + +IRObjectFile::IRObjectFile(MemoryBuffer *Object, error_code &EC, + LLVMContext &Context, bool BufferOwned) + : SymbolicFile(Binary::ID_IR, Object, BufferOwned) { + ErrorOr MOrErr = parseBitcodeFile(Object, Context); + if ((EC = MOrErr.getError())) + return; + + M.reset(MOrErr.get()); +} + +static const GlobalValue &getGV(DataRefImpl &Symb) { + return *reinterpret_cast(Symb.p & ~uintptr_t(3)); +} + +static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { + if (I == M.alias_end()) + return 3; + const GlobalValue *GV = &*I; + return reinterpret_cast(GV) | 2; +} + +static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) { + if (I == M.global_end()) + return skipEmpty(M.alias_begin(), M); + const GlobalValue *GV = &*I; + return reinterpret_cast(GV) | 1; +} + +static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { + if (I == M.end()) + return skipEmpty(M.global_begin(), M); + const GlobalValue *GV = &*I; + return reinterpret_cast(GV) | 0; +} + +void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { + const GlobalValue *GV = &getGV(Symb); + const Module &M = *GV->getParent(); + uintptr_t Res; + switch (Symb.p & 3) { + case 0: { + Module::const_iterator Iter(static_cast(GV)); + ++Iter; + Res = skipEmpty(Iter, M); + break; + } + case 1: { + Module::const_global_iterator Iter(static_cast(GV)); + ++Iter; + Res = skipEmpty(Iter, M); + break; + } + case 2: { + Module::const_alias_iterator Iter(static_cast(GV)); + ++Iter; + Res = skipEmpty(Iter, M); + break; + } + case 3: + llvm_unreachable("Invalid symbol reference"); + } + + Symb.p = Res; +} + +error_code IRObjectFile::printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const { + // FIXME: This should use the Mangler. + const GlobalValue &GV = getGV(Symb); + OS << GV.getName(); + return object_error::success; +} + +uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { + const GlobalValue &GV = getGV(Symb); + + uint32_t Res = BasicSymbolRef::SF_None; + if (GV.isDeclaration() || GV.hasAvailableExternallyLinkage()) + Res |= BasicSymbolRef::SF_Undefined; + if (GV.hasPrivateLinkage() || GV.hasLinkerPrivateLinkage() || + GV.hasLinkerPrivateWeakLinkage()) + Res |= BasicSymbolRef::SF_FormatSpecific; + if (!GV.hasLocalLinkage()) + Res |= BasicSymbolRef::SF_Global; + if (GV.hasCommonLinkage()) + Res |= BasicSymbolRef::SF_Common; + if (GV.hasLinkOnceLinkage() || GV.hasWeakLinkage()) + Res |= BasicSymbolRef::SF_Weak; + + return Res; +} + +const GlobalValue &IRObjectFile::getSymbolGV(DataRefImpl Symb) const { + const GlobalValue &GV = getGV(Symb); + return GV; +} + +basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { + Module::const_iterator I = M->begin(); + DataRefImpl Ret; + Ret.p = skipEmpty(I, *M); + return basic_symbol_iterator(BasicSymbolRef(Ret, this)); +} + +basic_symbol_iterator IRObjectFile::symbol_end_impl() const { + DataRefImpl Ret; + Ret.p = 3; + return basic_symbol_iterator(BasicSymbolRef(Ret, this)); +} + +ErrorOr llvm::object::SymbolicFile::createIRObjectFile( + MemoryBuffer *Object, LLVMContext &Context, bool BufferOwned) { + error_code EC; + OwningPtr Ret( + new IRObjectFile(Object, EC, Context, BufferOwned)); + if (EC) + return EC; + return Ret.take(); +} diff --git a/lib/Object/LLVMBuild.txt b/lib/Object/LLVMBuild.txt index 69610f991f..a87da6e5f4 100644 --- a/lib/Object/LLVMBuild.txt +++ b/lib/Object/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = Object parent = Libraries -required_libraries = Support +required_libraries = Support BitReader diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 23c2d6d8bd..09fe6a7571 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -1163,20 +1163,20 @@ error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); } -symbol_iterator MachOObjectFile::symbol_begin() const { +basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { DataRefImpl DRI; if (!SymtabLoadCmd) - return symbol_iterator(SymbolRef(DRI, this)); + return basic_symbol_iterator(SymbolRef(DRI, this)); MachO::symtab_command Symtab = getSymtabLoadCommand(); DRI.p = reinterpret_cast(getPtr(this, Symtab.symoff)); - return symbol_iterator(SymbolRef(DRI, this)); + return basic_symbol_iterator(SymbolRef(DRI, this)); } -symbol_iterator MachOObjectFile::symbol_end() const { +basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { DataRefImpl DRI; if (!SymtabLoadCmd) - return symbol_iterator(SymbolRef(DRI, this)); + return basic_symbol_iterator(SymbolRef(DRI, this)); MachO::symtab_command Symtab = getSymtabLoadCommand(); unsigned SymbolTableEntrySize = is64Bit() ? @@ -1185,7 +1185,7 @@ symbol_iterator MachOObjectFile::symbol_end() const { unsigned Offset = Symtab.symoff + Symtab.nsyms * SymbolTableEntrySize; DRI.p = reinterpret_cast(getPtr(this, Offset)); - return symbol_iterator(SymbolRef(DRI, this)); + return basic_symbol_iterator(SymbolRef(DRI, this)); } section_iterator MachOObjectFile::section_begin() const { diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index 2e6b9e6505..923baa58bc 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -25,7 +25,16 @@ void ObjectFile::anchor() { } ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *Source, bool BufferOwned) - : Binary(Type, Source, BufferOwned) {} + : SymbolicFile(Type, Source, BufferOwned) {} + +error_code ObjectFile::printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const { + StringRef Name; + if (error_code EC = getSymbolName(Symb, Name)) + return EC; + OS << Name; + return object_error::success; +} error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI, uint32_t &Result) const { diff --git a/lib/Object/SymbolicFile.cpp b/lib/Object/SymbolicFile.cpp new file mode 100644 index 0000000000..495f0b62bc --- /dev/null +++ b/lib/Object/SymbolicFile.cpp @@ -0,0 +1,67 @@ +//===- SymbolicFile.cpp - Interface that only provides symbols --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a file format independent SymbolicFile class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace llvm; +using namespace object; + +SymbolicFile::SymbolicFile(unsigned int Type, MemoryBuffer *Source, + bool BufferOwned) + : Binary(Type, Source, BufferOwned) {} + +SymbolicFile::~SymbolicFile() {} + +ErrorOr +SymbolicFile::createSymbolicFile(MemoryBuffer *Object, bool BufferOwned, + sys::fs::file_magic Type, + LLVMContext *Context) { + if (Type == sys::fs::file_magic::unknown) + Type = sys::fs::identify_magic(Object->getBuffer()); + + switch (Type) { + case sys::fs::file_magic::bitcode: + if (Context) + return IRObjectFile::createIRObjectFile(Object, *Context, BufferOwned); + // Fallthrough + case sys::fs::file_magic::unknown: + case sys::fs::file_magic::archive: + case sys::fs::file_magic::macho_universal_binary: + case sys::fs::file_magic::windows_resource: + if (BufferOwned) + delete Object; + return object_error::invalid_file_type; + case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::elf_executable: + case sys::fs::file_magic::elf_shared_object: + case sys::fs::file_magic::elf_core: + case sys::fs::file_magic::macho_object: + case sys::fs::file_magic::macho_executable: + case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: + case sys::fs::file_magic::macho_core: + case sys::fs::file_magic::macho_preload_executable: + case sys::fs::file_magic::macho_dynamically_linked_shared_lib: + case sys::fs::file_magic::macho_dynamic_linker: + case sys::fs::file_magic::macho_bundle: + case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: + case sys::fs::file_magic::macho_dsym_companion: + case sys::fs::file_magic::coff_object: + case sys::fs::file_magic::coff_import_library: + case sys::fs::file_magic::pecoff_executable: + return ObjectFile::createObjectFile(Object, BufferOwned, Type); + } + llvm_unreachable("Unexpected Binary File Type"); +} diff --git a/test/Object/nm-ir.ll b/test/Object/nm-ir.ll new file mode 100644 index 0000000000..ddf4125e39 --- /dev/null +++ b/test/Object/nm-ir.ll @@ -0,0 +1,34 @@ +; RUN: llvm-as %s -o - | llvm-nm - | FileCheck %s + +; CHECK: D a1 +; CHECK-NEXT: d a2 +; CHECK-NEXT: T f1 +; CHECK-NEXT: t f2 +; CHECK-NEXT: W f3 +; CHECK-NEXT: U f4 +; CHECK-NEXT: D g1 +; CHECK-NEXT: d g2 +; CHECK-NEXT: C g3 +; CHECK-NOT: g4 + +@g1 = global i32 42 +@g2 = internal global i32 42 +@g3 = common global i32 0 +@g4 = private global i32 42 + +@a1 = alias i32* @g1 +@a2 = alias internal i32* @g1 + +define void @f1() { + ret void +} + +define internal void @f2() { + ret void +} + +define linkonce_odr void @f3() { + ret void +} + +declare void @f4() diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index bc9ad37e5d..64d45bcb09 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -696,18 +696,21 @@ static void writeSymbolTable( std::vector > &MemberOffsetRefs) { unsigned StartOffset = 0; unsigned MemberNum = 0; - std::vector SymNames; - std::vector DeleteIt; + std::string NameBuf; + raw_string_ostream NameOS(NameBuf); + unsigned NumSyms = 0; + std::vector DeleteIt; + LLVMContext &Context = getGlobalContext(); for (ArrayRef::iterator I = Members.begin(), E = Members.end(); I != E; ++I, ++MemberNum) { MemoryBuffer *MemberBuffer = Buffers[MemberNum]; - ErrorOr ObjOrErr = - object::ObjectFile::createObjectFile(MemberBuffer, false, - sys::fs::file_magic::unknown); + ErrorOr ObjOrErr = + object::SymbolicFile::createSymbolicFile( + MemberBuffer, false, sys::fs::file_magic::unknown, &Context); if (!ObjOrErr) continue; // FIXME: check only for "not an object file" errors. - object::ObjectFile *Obj = ObjOrErr.get(); + object::SymbolicFile *Obj = ObjOrErr.get(); DeleteIt.push_back(Obj); if (!StartOffset) { @@ -716,34 +719,29 @@ static void writeSymbolTable( print32BE(Out, 0); } - for (object::symbol_iterator I = Obj->symbol_begin(), - E = Obj->symbol_end(); + for (object::basic_symbol_iterator I = Obj->symbol_begin(), + E = Obj->symbol_end(); I != E; ++I) { - uint32_t Symflags = I->getFlags();; + uint32_t Symflags = I->getFlags(); if (Symflags & object::SymbolRef::SF_FormatSpecific) continue; if (!(Symflags & object::SymbolRef::SF_Global)) continue; if (Symflags & object::SymbolRef::SF_Undefined) continue; - StringRef Name; - failIfError(I->getName(Name)); - SymNames.push_back(Name); + failIfError(I->printName(NameOS)); + NameOS << '\0'; + ++NumSyms; MemberOffsetRefs.push_back(std::make_pair(Out.tell(), MemberNum)); print32BE(Out, 0); } } - for (std::vector::iterator I = SymNames.begin(), - E = SymNames.end(); - I != E; ++I) { - Out << *I; - Out << '\0'; - } + Out << NameOS.str(); - for (std::vector::iterator I = DeleteIt.begin(), - E = DeleteIt.end(); + for (std::vector::iterator I = DeleteIt.begin(), + E = DeleteIt.end(); I != E; ++I) { - object::ObjectFile *O = *I; + object::SymbolicFile *O = *I; delete O; } @@ -757,7 +755,7 @@ static void writeSymbolTable( Out.seek(StartOffset - 12); printWithSpacePadding(Out, Pos - StartOffset, 10); Out.seek(StartOffset); - print32BE(Out, SymNames.size()); + print32BE(Out, NumSyms); Out.seek(Pos); } diff --git a/tools/llvm-nm/CMakeLists.txt b/tools/llvm-nm/CMakeLists.txt index ce758ced44..6128bf9adf 100644 --- a/tools/llvm-nm/CMakeLists.txt +++ b/tools/llvm-nm/CMakeLists.txt @@ -1,6 +1,4 @@ set(LLVM_LINK_COMPONENTS - BitReader - Core Object Support ) diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index fd18454a8f..d93177e245 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -16,11 +16,13 @@ // //===----------------------------------------------------------------------===// +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/IR/Module.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/IRObjectFile.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" @@ -53,8 +55,7 @@ cl::opt OutputFormat( cl::alias OutputFormat2("f", cl::desc("Alias for --format"), cl::aliasopt(OutputFormat)); -cl::list InputFilenames(cl::Positional, - cl::desc(""), +cl::list InputFilenames(cl::Positional, cl::desc(""), cl::ZeroOrMore); cl::opt UndefinedOnly("undefined-only", @@ -250,67 +251,15 @@ static void sortAndPrintSymbolList() { SymbolList.clear(); } -static char typeCharForSymbol(GlobalValue &GV) { - if (GV.isDeclaration()) - return 'U'; - if (GV.hasLinkOnceLinkage()) - return 'C'; - if (GV.hasCommonLinkage()) - return 'C'; - if (GV.hasWeakLinkage()) - return 'W'; - if (isa(GV) && GV.hasInternalLinkage()) - return 't'; - if (isa(GV)) - return 'T'; - if (isa(GV) && GV.hasInternalLinkage()) - return 'd'; - if (isa(GV)) - return 'D'; - if (const GlobalAlias *GA = dyn_cast(&GV)) { - const GlobalValue *AliasedGV = GA->getAliasedGlobal(); - if (isa(AliasedGV)) - return 'T'; - if (isa(AliasedGV)) - return 'D'; - } - return '?'; -} - -static void dumpSymbolNameForGlobalValue(GlobalValue &GV) { - // Private linkage and available_externally linkage don't exist in symtab. - if (GV.hasPrivateLinkage() || GV.hasLinkerPrivateLinkage() || - GV.hasLinkerPrivateWeakLinkage() || GV.hasAvailableExternallyLinkage()) - return; - char TypeChar = typeCharForSymbol(GV); - if (GV.hasLocalLinkage() && ExternalOnly) - return; - - NMSymbol S; - S.Address = UnknownAddressOrSize; - S.Size = UnknownAddressOrSize; - S.TypeChar = TypeChar; - S.Name = GV.getName(); - SymbolList.push_back(S); -} - -static void dumpSymbolNamesFromModule(Module *M) { - CurrentFilename = M->getModuleIdentifier(); - std::for_each(M->begin(), M->end(), dumpSymbolNameForGlobalValue); - std::for_each(M->global_begin(), M->global_end(), - dumpSymbolNameForGlobalValue); - if (!WithoutAliases) - std::for_each(M->alias_begin(), M->alias_end(), - dumpSymbolNameForGlobalValue); - - sortAndPrintSymbolList(); -} - template -static char getSymbolNMTypeChar(ELFObjectFile &Obj, symbol_iterator I) { +static char getSymbolNMTypeChar(ELFObjectFile &Obj, + basic_symbol_iterator I) { typedef typename ELFObjectFile::Elf_Sym Elf_Sym; typedef typename ELFObjectFile::Elf_Shdr Elf_Shdr; + // OK, this is ELF + symbol_iterator SymI(I); + DataRefImpl Symb = I->getRawDataRefImpl(); const Elf_Sym *ESym = Obj.getSymbol(Symb); const ELFFile &EF = *Obj.getELFFile(); @@ -339,7 +288,7 @@ static char getSymbolNMTypeChar(ELFObjectFile &Obj, symbol_iterator I) { if (ESym->getType() == ELF::STT_SECTION) { StringRef Name; - if (error(I->getName(Name))) + if (error(SymI->getName(Name))) return '?'; return StringSwitch(Name) .StartsWith(".debug", 'N') @@ -352,9 +301,13 @@ static char getSymbolNMTypeChar(ELFObjectFile &Obj, symbol_iterator I) { static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { const coff_symbol *Symb = Obj.getCOFFSymbol(I); + // OK, this is COFF. + symbol_iterator SymI(I); + StringRef Name; - if (error(I->getName(Name))) + if (error(SymI->getName(Name))) return '?'; + char Ret = StringSwitch(Name) .StartsWith(".debug", 'N') .StartsWith(".sxdata", 'N') @@ -366,7 +319,7 @@ static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { uint32_t Characteristics = 0; if (Symb->SectionNumber > 0) { section_iterator SecI = Obj.section_end(); - if (error(I->getSection(SecI))) + if (error(SymI->getSection(SecI))) return '?'; const coff_section *Section = Obj.getCOFFSection(SecI); Characteristics = Section->Characteristics; @@ -407,7 +360,7 @@ static uint8_t getNType(MachOObjectFile &Obj, DataRefImpl Symb) { return STE.n_type; } -static char getSymbolNMTypeChar(MachOObjectFile &Obj, symbol_iterator I) { +static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { DataRefImpl Symb = I->getRawDataRefImpl(); uint8_t NType = getNType(Obj, Symb); @@ -431,6 +384,23 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, symbol_iterator I) { return '?'; } +static char getSymbolNMTypeChar(const GlobalValue &GV) { + if (isa(GV)) + return 't'; + // FIXME: should we print 'b'? At the IR level we cannot be sure if this + // will be in bss or not, but we could approximate. + if (isa(GV)) + return 'd'; + const GlobalAlias *GA = cast(&GV); + const GlobalValue *AliasedGV = GA->getAliasedGlobal(); + return getSymbolNMTypeChar(*AliasedGV); +} + +static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) { + const GlobalValue &GV = Obj.getSymbolGV(I->getRawDataRefImpl()); + return getSymbolNMTypeChar(GV); +} + template static bool isObject(ELFObjectFile &Obj, symbol_iterator I) { typedef typename ELFObjectFile::Elf_Sym Elf_Sym; @@ -441,7 +411,7 @@ static bool isObject(ELFObjectFile &Obj, symbol_iterator I) { return ESym->getType() == ELF::STT_OBJECT; } -static bool isObject(ObjectFile *Obj, symbol_iterator I) { +static bool isObject(SymbolicFile *Obj, basic_symbol_iterator I) { if (ELF32LEObjectFile *ELF = dyn_cast(Obj)) return isObject(*ELF, I); if (ELF64LEObjectFile *ELF = dyn_cast(Obj)) @@ -453,7 +423,7 @@ static bool isObject(ObjectFile *Obj, symbol_iterator I) { return false; } -static char getNMTypeChar(ObjectFile *Obj, symbol_iterator I) { +static char getNMTypeChar(SymbolicFile *Obj, basic_symbol_iterator I) { uint32_t Symflags = I->getFlags(); if ((Symflags & object::SymbolRef::SF_Weak) && !isa(Obj)) { char Ret = isObject(Obj, I) ? 'v' : 'w'; @@ -471,6 +441,8 @@ static char getNMTypeChar(ObjectFile *Obj, symbol_iterator I) { char Ret = '?'; if (Symflags & object::SymbolRef::SF_Absolute) Ret = 'a'; + else if (IRObjectFile *IR = dyn_cast(Obj)) + Ret = getSymbolNMTypeChar(*IR, I); else if (COFFObjectFile *COFF = dyn_cast(Obj)) Ret = getSymbolNMTypeChar(*COFF, I); else if (MachOObjectFile *MachO = dyn_cast(Obj)) @@ -490,8 +462,9 @@ static char getNMTypeChar(ObjectFile *Obj, symbol_iterator I) { return Ret; } -static void getDynamicSymbolIterators(ObjectFile *Obj, symbol_iterator &Begin, - symbol_iterator &End) { +static void getDynamicSymbolIterators(SymbolicFile *Obj, + basic_symbol_iterator &Begin, + basic_symbol_iterator &End) { if (ELF32LEObjectFile *ELF = dyn_cast(Obj)) { Begin = ELF->dynamic_symbol_begin(); End = ELF->dynamic_symbol_end(); @@ -513,9 +486,9 @@ static void getDynamicSymbolIterators(ObjectFile *Obj, symbol_iterator &Begin, return; } -static void dumpSymbolNamesFromObject(ObjectFile *Obj) { - symbol_iterator IBegin = Obj->symbol_begin(); - symbol_iterator IEnd = Obj->symbol_end(); +static void dumpSymbolNamesFromObject(SymbolicFile *Obj) { + basic_symbol_iterator IBegin = Obj->symbol_begin(); + basic_symbol_iterator IEnd = Obj->symbol_end(); if (DynamicSyms) { if (!Obj->isELF()) { error("File format has no dynamic symbol table", Obj->getFileName()); @@ -523,26 +496,44 @@ static void dumpSymbolNamesFromObject(ObjectFile *Obj) { } getDynamicSymbolIterators(Obj, IBegin, IEnd); } - for (symbol_iterator I = IBegin; I != IEnd; ++I) { + std::string NameBuffer; + raw_string_ostream OS(NameBuffer); + for (basic_symbol_iterator I = IBegin; I != IEnd; ++I) { uint32_t SymFlags = I->getFlags(); if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific)) continue; + if (WithoutAliases) { + if (IRObjectFile *IR = dyn_cast(Obj)) { + const GlobalValue &GV = IR->getSymbolGV(I->getRawDataRefImpl()); + if(isa(GV)) + continue; + } + } NMSymbol S; S.Size = UnknownAddressOrSize; S.Address = UnknownAddressOrSize; - if (PrintSize || SizeSort) { - if (error(I->getSize(S.Size))) + if ((PrintSize || SizeSort) && isa(Obj)) { + symbol_iterator SymI = I; + if (error(SymI->getSize(S.Size))) break; } - if (PrintAddress) - if (error(I->getAddress(S.Address))) + if (PrintAddress && isa(Obj)) + if (error(symbol_iterator(I)->getAddress(S.Address))) break; S.TypeChar = getNMTypeChar(Obj, I); - if (error(I->getName(S.Name))) + if (error(I->printName(OS))) break; + OS << '\0'; SymbolList.push_back(S); } + OS.flush(); + const char *P = NameBuffer.c_str(); + for (unsigned I = 0; I < SymbolList.size(); ++I) { + SymbolList[I].Name = P; + P += strlen(P) + 1; + } + CurrentFilename = Obj->getFileName(); sortAndPrintSymbolList(); } @@ -552,22 +543,8 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { if (error(MemoryBuffer::getFileOrSTDIN(Filename, Buffer), Filename)) return; - sys::fs::file_magic Magic = sys::fs::identify_magic(Buffer->getBuffer()); - LLVMContext &Context = getGlobalContext(); - if (Magic == sys::fs::file_magic::bitcode) { - ErrorOr ModuleOrErr = parseBitcodeFile(Buffer.get(), Context); - if (error(ModuleOrErr.getError(), Filename)) { - return; - } else { - Module *Result = ModuleOrErr.get(); - dumpSymbolNamesFromModule(Result); - delete Result; - } - return; - } - - ErrorOr BinaryOrErr = createBinary(Buffer.take(), Magic); + ErrorOr BinaryOrErr = createBinary(Buffer.take(), &Context); if (error(BinaryOrErr.getError(), Filename)) return; OwningPtr Bin(BinaryOrErr.get()); @@ -597,29 +574,16 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E; ++I) { OwningPtr Child; - if (I->getAsBinary(Child)) { - // Try opening it as a bitcode file. - OwningPtr Buff; - if (error(I->getMemoryBuffer(Buff))) - return; - - ErrorOr ModuleOrErr = parseBitcodeFile(Buff.get(), Context); - if (ModuleOrErr) { - Module *Result = ModuleOrErr.get(); - dumpSymbolNamesFromModule(Result); - delete Result; - } + if (I->getAsBinary(Child, &Context)) continue; - } - if (ObjectFile *O = dyn_cast(Child.get())) { + if (SymbolicFile *O = dyn_cast(Child.get())) { outs() << O->getFileName() << ":\n"; dumpSymbolNamesFromObject(O); } } return; } - if (MachOUniversalBinary *UB = - dyn_cast(Bin.get())) { + if (MachOUniversalBinary *UB = dyn_cast(Bin.get())) { for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), E = UB->end_objects(); I != E; ++I) { @@ -631,7 +595,7 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { } return; } - if (ObjectFile *O = dyn_cast(Bin.get())) { + if (SymbolicFile *O = dyn_cast(Bin.get())) { dumpSymbolNamesFromObject(O); return; } -- cgit v1.2.3