mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-12 13:38:21 +00:00
Adding changes to support GNU style archive library reading
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167853 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -122,7 +122,14 @@ error_code Archive::Child::getName(StringRef &Result) const {
|
||||
+ sizeof(ArchiveMemberHeader)
|
||||
+ Parent->StringTable->getSize()))
|
||||
return object_error::parse_failed;
|
||||
Result = addr;
|
||||
|
||||
// GNU long file names end with 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,15 +194,52 @@ Archive::Archive(MemoryBuffer *source, error_code &ec)
|
||||
child_iterator i = begin_children(false);
|
||||
child_iterator e = end_children();
|
||||
|
||||
if (i != e) ++i; // Nobody cares about the first member.
|
||||
if (i != e) {
|
||||
SymbolTable = i;
|
||||
++i;
|
||||
}
|
||||
if (i != e) {
|
||||
StringTable = i;
|
||||
}
|
||||
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;
|
||||
if (name[0] != '/') {
|
||||
Format = K_GNU;
|
||||
} else if ((name.size() > 1) && (name == "//")) {
|
||||
Format = K_GNU;
|
||||
StringTable = i;
|
||||
++i;
|
||||
} else {
|
||||
Format = K_COFF;
|
||||
if (i != e) {
|
||||
SymbolTable = i;
|
||||
++i;
|
||||
}
|
||||
if (i != e) {
|
||||
StringTable = i;
|
||||
}
|
||||
}
|
||||
} else if (name == "__.SYMDEF") {
|
||||
Format = K_BSD;
|
||||
SymbolTable = i;
|
||||
StringTable = e;
|
||||
}
|
||||
ec = object_error::success;
|
||||
}
|
||||
|
||||
@ -222,17 +266,28 @@ error_code Archive::Symbol::getName(StringRef &Result) const {
|
||||
|
||||
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.
|
||||
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));
|
||||
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 *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 +308,20 @@ Archive::Symbol Archive::Symbol::getNext() const {
|
||||
|
||||
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.
|
||||
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.
|
||||
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 +329,36 @@ Archive::symbol_iterator Archive::begin_symbols() const {
|
||||
|
||||
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);
|
||||
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.
|
||||
symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
|
||||
}
|
||||
return symbol_iterator(
|
||||
Symbol(this, symbol_count, 0));
|
||||
}
|
||||
|
||||
Archive::child_iterator Archive::findSym(StringRef name) const {
|
||||
Archive::symbol_iterator bs = begin_symbols();
|
||||
Archive::symbol_iterator es = end_symbols();
|
||||
Archive::child_iterator result;
|
||||
|
||||
StringRef symname;
|
||||
for (; bs != es; ++bs) {
|
||||
if (bs->getName(symname))
|
||||
return end_children();
|
||||
if (symname == name) {
|
||||
if (bs->getMember(result))
|
||||
return end_children();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return end_children();
|
||||
}
|
||||
|
Reference in New Issue
Block a user