Object/Archive: Add symbol table iteration.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@143561 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Michael J. Spencer 2011-11-02 19:33:12 +00:00
parent e07cd5e40a
commit c8a55a660e
2 changed files with 117 additions and 9 deletions

View File

@ -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;
};

View File

@ -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<Binary> &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<const support::ulittle32_t*>(buf);
const char *offsets = buf + 4;
buf += 4 + (member_count * 4); // Skip offsets.
uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
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)
+ (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<const support::ulittle32_t*>(buf);
buf += 4 + (member_count * 4); // Skip offsets.
uint32_t 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));
}
Archive::symbol_iterator Archive::end_symbols() const {
const char *buf = SymbolTable->getBuffer()->getBufferStart();
uint32_t 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);
return symbol_iterator(
Symbol(this, symbol_count, 0));
}