From c8a55a660e93bb7a4854969b4c5814bf7bb0101b Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Wed, 2 Nov 2011 19:33:12 +0000 Subject: [PATCH] Object/Archive: Add symbol table iteration. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@143561 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/Archive.h | 46 ++++++++++++++++++++ lib/Object/Archive.cpp | 80 +++++++++++++++++++++++++++++++---- 2 files changed, 117 insertions(+), 9 deletions(-) diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index d72037020ae..b12b17e1f5b 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -50,6 +50,7 @@ public: class child_iterator { Child child; public: + child_iterator() : child(Child(0, StringRef())) {} child_iterator(const Child &c) : child(c) {} const Child* operator->() const { return &child; @@ -69,11 +70,55 @@ public: } }; + class Symbol { + const Archive *Parent; + uint32_t SymbolIndex; + uint32_t StringIndex; // Extra index to the string. + + public: + bool operator ==(const Symbol &other) const { + return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex); + } + + Symbol(const Archive *p, uint32_t symi, uint32_t stri) + : Parent(p) + , SymbolIndex(symi) + , StringIndex(stri) {} + error_code getName(StringRef &Result) const; + error_code getMember(child_iterator &Result) const; + Symbol getNext() const; + }; + + class symbol_iterator { + Symbol symbol; + public: + symbol_iterator(const Symbol &s) : symbol(s) {} + const Symbol *operator->() const { + return &symbol; + } + + bool operator==(const symbol_iterator &other) const { + return symbol == other.symbol; + } + + bool operator!=(const symbol_iterator &other) const { + return !(*this == other); + } + + symbol_iterator& operator++() { // Preincrement + symbol = symbol.getNext(); + return *this; + } + }; + Archive(MemoryBuffer *source, error_code &ec); child_iterator begin_children(bool skip_internal = true) const; child_iterator end_children() const; + symbol_iterator begin_symbols() const; + symbol_iterator end_symbols() const; + // Cast methods. static inline bool classof(Archive const *v) { return true; } static inline bool classof(Binary const *v) { @@ -81,6 +126,7 @@ public: } private: + child_iterator SymbolTable; child_iterator StringTable; }; diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index f1c4b2d7961..968ddcdcffc 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -13,6 +13,7 @@ #include "llvm/Object/Archive.h" #include "llvm/ADT/APInt.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" using namespace llvm; @@ -171,8 +172,7 @@ error_code Archive::Child::getAsBinary(OwningPtr &Result) const { } Archive::Archive(MemoryBuffer *source, error_code &ec) - : Binary(Binary::isArchive, source) - , StringTable(Child(this, StringRef(0, 0))) { + : Binary(Binary::isArchive, source) { // Check for sufficient magic. if (!source || source->getBufferSize() < (8 + sizeof(ArchiveMemberHeader) + 2) // Smallest archive. @@ -181,15 +181,18 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) return; } - // Get the string table. It's the 3rd member. - child_iterator StrTable = begin_children(false); + // Get the special members. + child_iterator i = begin_children(false); child_iterator e = end_children(); - for (int i = 0; StrTable != e && i < 2; ++StrTable, ++i) {} - // Check to see if there were 3 members, or the 3rd member wasn't named "//". - StringRef name; - if (StrTable != e && !StrTable->getName(name) && name == "//") - StringTable = StrTable; + if (i != e) ++i; // Nobody cares about the first member. + if (i != e) { + SymbolTable = i; + ++i; + } + if (i != e) { + StringTable = i; + } ec = object_error::success; } @@ -208,3 +211,62 @@ Archive::child_iterator Archive::begin_children(bool skip_internal) const { Archive::child_iterator Archive::end_children() const { return Child(this, StringRef(0, 0)); } + +error_code Archive::Symbol::getName(StringRef &Result) const { + Result = + StringRef(Parent->SymbolTable->getBuffer()->getBufferStart() + StringIndex); + return object_error::success; +} + +error_code Archive::Symbol::getMember(child_iterator &Result) const { + const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart(); + uint32_t member_count = *reinterpret_cast(buf); + const char *offsets = buf + 4; + buf += 4 + (member_count * 4); // Skip offsets. + uint32_t symbol_count = *reinterpret_cast(buf); + const char *indicies = buf + 4; + + uint16_t offsetindex = + *(reinterpret_cast(indicies) + + SymbolIndex); + + uint32_t offset = *(reinterpret_cast(offsets) + + (offsetindex - 1)); + + const char *Loc = Parent->getData().begin() + offset; + size_t Size = sizeof(ArchiveMemberHeader) + + ToHeader(Loc)->getSize(); + Result = Child(Parent, StringRef(Loc, Size)); + + return object_error::success; +} + +Archive::Symbol Archive::Symbol::getNext() const { + Symbol t(*this); + const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart(); + buf += t.StringIndex; + while (*buf++); // Go to one past next null. + t.StringIndex = buf - Parent->SymbolTable->getBuffer()->getBufferStart(); + ++t.SymbolIndex; + return t; +} + +Archive::symbol_iterator Archive::begin_symbols() const { + const char *buf = SymbolTable->getBuffer()->getBufferStart(); + uint32_t member_count = *reinterpret_cast(buf); + buf += 4 + (member_count * 4); // Skip offsets. + uint32_t symbol_count = *reinterpret_cast(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)); +} + +Archive::symbol_iterator Archive::end_symbols() const { + const char *buf = SymbolTable->getBuffer()->getBufferStart(); + uint32_t member_count = *reinterpret_cast(buf); + buf += 4 + (member_count * 4); // Skip offsets. + uint32_t symbol_count = *reinterpret_cast(buf); + return symbol_iterator( + Symbol(this, symbol_count, 0)); +}