mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 22:04:55 +00:00
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:
parent
e07cd5e40a
commit
c8a55a660e
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user