diff options
author | Kevin Enderby <enderby@apple.com> | 2014-07-08 22:10:02 +0000 |
---|---|---|
committer | Kevin Enderby <enderby@apple.com> | 2014-07-08 22:10:02 +0000 |
commit | 8c50dbb8cb731db841c99e9e7c126e7298d2aeff (patch) | |
tree | 5c100711cec9f165a97cc6dce5f8e02720225d88 /llvm/lib | |
parent | 389be9558fdd632bcc460da265db9d30484f3ced (diff) | |
download | bcm5719-llvm-8c50dbb8cb731db841c99e9e7c126e7298d2aeff.tar.gz bcm5719-llvm-8c50dbb8cb731db841c99e9e7c126e7298d2aeff.zip |
Add support for BSD format Archive map symbols (aka the table of contents
from a __.SYMDEF or "__.SYMDEF SORTED" archive member).
llvm-svn: 212568
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Object/Archive.cpp | 69 |
1 files changed, 63 insertions, 6 deletions
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp index 2393ade562d..6d09bdbac06 100644 --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -339,7 +339,14 @@ ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const { Offset = *(reinterpret_cast<const support::ubig32_t*>(Offsets) + SymbolIndex); } else if (Parent->kind() == K_BSD) { - llvm_unreachable("BSD format is not supported"); + // The SymbolIndex is an index into the ranlib structs that start at + // Offsets (the first uint32_t is the number of bytes of the ranlib + // structs). The ranlib structs are a pair of uint32_t's the first + // being a string table offset and the second being the offset into + // the archive of the member that defines the symbol. Which is what + // is needed here. + Offset = *(reinterpret_cast<const support::ulittle32_t *>(Offsets) + + (SymbolIndex * 2) + 1); } else { uint32_t MemberCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); @@ -377,9 +384,43 @@ ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const { Archive::Symbol Archive::Symbol::getNext() const { Symbol t(*this); - // Go to one past next null. - t.StringIndex = - Parent->SymbolTable->getBuffer().find('\0', t.StringIndex) + 1; + if (Parent->kind() == K_BSD) { + // t.StringIndex is an offset from the start of the __.SYMDEF or + // "__.SYMDEF SORTED" member into the string table for the ranlib + // struct indexed by t.SymbolIndex . To change t.StringIndex to the + // offset in the string table for t.SymbolIndex+1 we subtract the + // its offset from the start of the string table for t.SymbolIndex + // and add the offset of the string table for t.SymbolIndex+1. + + // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t + // which is the number of bytes of ranlib structs that follow. The ranlib + // structs are a pair of uint32_t's the first being a string table offset + // and the second being the offset into the archive of the member that + // define the symbol. After that the next uint32_t is the byte count of + // the string table followed by the string table. + const char *Buf = Parent->SymbolTable->getBuffer().begin(); + uint32_t RanlibCount = 0; + RanlibCount = (*reinterpret_cast<const support::ulittle32_t *>(Buf)) / + (sizeof(uint32_t) * 2); + // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount) + // don't change the t.StringIndex as we don't want to reference a ranlib + // past RanlibCount. + if (t.SymbolIndex + 1 < RanlibCount) { + const char *Ranlibs = Buf + 4; + uint32_t CurRanStrx = 0; + uint32_t NextRanStrx = 0; + CurRanStrx = *(reinterpret_cast<const support::ulittle32_t *>(Ranlibs) + + (t.SymbolIndex * 2)); + NextRanStrx = *(reinterpret_cast<const support::ulittle32_t *>(Ranlibs) + + ((t.SymbolIndex + 1) * 2)); + t.StringIndex -= CurRanStrx; + t.StringIndex += NextRanStrx; + } + } else { + // Go to one past next null. + t.StringIndex = + Parent->SymbolTable->getBuffer().find('\0', t.StringIndex) + 1; + } ++t.SymbolIndex; return t; } @@ -394,7 +435,22 @@ Archive::symbol_iterator Archive::symbol_begin() const { symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf); buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); } else if (kind() == K_BSD) { - llvm_unreachable("BSD archive format is not supported"); + // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t + // which is the number of bytes of ranlib structs that follow. The ranlib + // structs are a pair of uint32_t's the first being a string table offset + // and the second being the offset into the archive of the member that + // define the symbol. After that the next uint32_t is the byte count of + // the string table followed by the string table. + uint32_t ranlib_count = 0; + ranlib_count = (*reinterpret_cast<const support::ulittle32_t *>(buf)) / + (sizeof(uint32_t) * 2); + const char *ranlibs = buf + 4; + uint32_t ran_strx = 0; + ran_strx = *(reinterpret_cast<const support::ulittle32_t *>(ranlibs)); + buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t)))); + // Skip the byte count of the string table. + buf += sizeof(uint32_t); + buf += ran_strx; } else { uint32_t member_count = 0; uint32_t symbol_count = 0; @@ -416,7 +472,8 @@ Archive::symbol_iterator Archive::symbol_end() const { if (kind() == K_GNU) { symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf); } else if (kind() == K_BSD) { - llvm_unreachable("BSD archive format is not supported"); + symbol_count = (*reinterpret_cast<const support::ulittle32_t *>(buf)) / + (sizeof(uint32_t) * 2); } else { uint32_t member_count = 0; member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); |