From 206252cc9f5509b27aa0761c677fdee8daff001c Mon Sep 17 00:00:00 2001 From: Shankar Easwaran Date: Tue, 13 Nov 2012 18:38:42 +0000 Subject: 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 --- lib/Object/Archive.cpp | 144 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 118 insertions(+), 26 deletions(-) (limited to 'lib/Object/Archive.cpp') diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 2a5951ada5..b55dab8f85 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -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/, 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(buf); const char *offsets = buf + 4; - buf += 4 + (member_count * 4); // Skip offsets. - const char *indicies = buf + 4; - - uint16_t offsetindex = - *(reinterpret_cast(indicies) - + SymbolIndex); - - uint32_t offset = *(reinterpret_cast(offsets) - + (offsetindex - 1)); + uint32_t offset = 0; + if (Parent->kind() == K_GNU) { + offset = *(reinterpret_cast(offsets) + + SymbolIndex); + } else if (Parent->kind() == K_BSD) { + assert("BSD format is not supported"); + } else { + uint32_t member_count = 0; + member_count = *reinterpret_cast(buf); + buf += 4 + (member_count * 4); // Skip offsets. + const char *indicies = buf + 4; + uint16_t offsetindex = + *(reinterpret_cast(indicies) + + SymbolIndex); + uint32_t *offsetaddr = + (uint32_t *)(reinterpret_cast(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(buf); - buf += 4 + (member_count * 4); // Skip offsets. - uint32_t symbol_count = *reinterpret_cast(buf); - buf += 4 + (symbol_count * 2); // Skip indices. + if (kind() == K_GNU) { + uint32_t symbol_count = 0; + symbol_count = *reinterpret_cast(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(buf); + buf += 4 + (member_count * 4); // Skip offsets. + 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)); @@ -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(buf); - buf += 4 + (member_count * 4); // Skip offsets. - uint32_t symbol_count = *reinterpret_cast(buf); + uint32_t symbol_count = 0; + if (kind() == K_GNU) { + symbol_count = *reinterpret_cast(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(buf); + buf += 4 + (member_count * 4); // Skip offsets. + symbol_count = *reinterpret_cast(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(); +} -- cgit v1.2.3 From 768a707fdfd0be3587864b9b9edcc74aa0acdf92 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Wed, 14 Nov 2012 00:04:13 +0000 Subject: [Object] Fix endianess bug by refactoring Archive::Symbol::getMember. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167893 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/Archive.cpp | 50 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 18 deletions(-) (limited to 'lib/Object/Archive.cpp') diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index b55dab8f85..28d052e12d 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -265,31 +265,45 @@ error_code Archive::Symbol::getName(StringRef &Result) const { } error_code Archive::Symbol::getMember(child_iterator &Result) const { - const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart(); - const char *offsets = buf + 4; - uint32_t offset = 0; + const char *Buf = Parent->SymbolTable->getBuffer()->getBufferStart(); + const char *Offsets = Buf + 4; + uint32_t Offset = 0; if (Parent->kind() == K_GNU) { - offset = *(reinterpret_cast(offsets) - + SymbolIndex); + Offset = *(reinterpret_cast(Offsets) + + SymbolIndex); } else if (Parent->kind() == K_BSD) { assert("BSD format is not supported"); } else { - uint32_t member_count = 0; - member_count = *reinterpret_cast(buf); - buf += 4 + (member_count * 4); // Skip offsets. - const char *indicies = buf + 4; - uint16_t offsetindex = - *(reinterpret_cast(indicies) + uint32_t MemberCount = *reinterpret_cast(Buf); + + // Skip offsets. + Buf += sizeof(support::ulittle32_t) + + (MemberCount * sizeof(support::ulittle32_t)); + + uint32_t SymbolCount = *reinterpret_cast(Buf); + + if (SymbolIndex >= SymbolCount) + return object_error::parse_failed; + + // Skip SymbolCount to get to the indicies table. + const char *Indicies = Buf + sizeof(support::ulittle32_t); + + // Get the index of the offset in the file member offset table for this + // symbol. + uint16_t OffsetIndex = + *(reinterpret_cast(Indicies) + SymbolIndex); - uint32_t *offsetaddr = - (uint32_t *)(reinterpret_cast(offsets) - + (offsetindex - 1)); - assert((const char *)offsetaddr < - Parent->SymbolTable->getBuffer()->getBufferEnd()); - offset = *(offsetaddr); + // Subtract 1 since OffsetIndex is 1 based. + --OffsetIndex; + + if (OffsetIndex >= MemberCount) + return object_error::parse_failed; + + Offset = *(reinterpret_cast(Offsets) + + OffsetIndex); } - const char *Loc = Parent->getData().begin() + offset; + const char *Loc = Parent->getData().begin() + Offset; size_t Size = sizeof(ArchiveMemberHeader) + ToHeader(Loc)->getSize(); Result = Child(Parent, StringRef(Loc, Size)); -- cgit v1.2.3 From f1c2a6b512c5e210c8571923663fe19c713ea45d Mon Sep 17 00:00:00 2001 From: Matt Beaumont-Gay Date: Wed, 14 Nov 2012 00:21:27 +0000 Subject: Fix broken asserts. Also, spell 'indices' correctly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167894 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/Archive.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/Object/Archive.cpp') diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 28d052e12d..12ec3ce929 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -272,7 +272,7 @@ error_code Archive::Symbol::getMember(child_iterator &Result) const { Offset = *(reinterpret_cast(Offsets) + SymbolIndex); } else if (Parent->kind() == K_BSD) { - assert("BSD format is not supported"); + assert(0 && "BSD format is not supported"); } else { uint32_t MemberCount = *reinterpret_cast(Buf); @@ -285,13 +285,13 @@ error_code Archive::Symbol::getMember(child_iterator &Result) const { if (SymbolIndex >= SymbolCount) return object_error::parse_failed; - // Skip SymbolCount to get to the indicies table. - const char *Indicies = Buf + sizeof(support::ulittle32_t); + // Skip SymbolCount to get to the indices table. + const char *Indices = Buf + sizeof(support::ulittle32_t); // Get the index of the offset in the file member offset table for this // symbol. uint16_t OffsetIndex = - *(reinterpret_cast(Indicies) + *(reinterpret_cast(Indices) + SymbolIndex); // Subtract 1 since OffsetIndex is 1 based. --OffsetIndex; @@ -327,7 +327,7 @@ Archive::symbol_iterator Archive::begin_symbols() const { symbol_count = *reinterpret_cast(buf); buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); } else if (kind() == K_BSD) { - assert("BSD archive format is not supported"); + assert(0 && "BSD archive format is not supported"); } else { uint32_t member_count = 0; uint32_t symbol_count = 0; @@ -348,7 +348,7 @@ Archive::symbol_iterator Archive::end_symbols() const { symbol_count = *reinterpret_cast(buf); buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); } else if (kind() == K_BSD) { - assert("BSD archive format is not supported"); + assert(0 && "BSD archive format is not supported"); } else { uint32_t member_count = 0; member_count = *reinterpret_cast(buf); -- cgit v1.2.3 From 7af4b9b33a2bc3e95f78d8b5063a77035c86640d Mon Sep 17 00:00:00 2001 From: Matt Beaumont-Gay Date: Wed, 14 Nov 2012 17:58:11 +0000 Subject: s/assert/llvm_unreachable/ git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167936 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/Archive.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/Object/Archive.cpp') diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 12ec3ce929..5b1e007e85 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/ErrorHandling.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" @@ -272,7 +273,7 @@ error_code Archive::Symbol::getMember(child_iterator &Result) const { Offset = *(reinterpret_cast(Offsets) + SymbolIndex); } else if (Parent->kind() == K_BSD) { - assert(0 && "BSD format is not supported"); + llvm_unreachable("BSD format is not supported"); } else { uint32_t MemberCount = *reinterpret_cast(Buf); @@ -327,7 +328,7 @@ Archive::symbol_iterator Archive::begin_symbols() const { symbol_count = *reinterpret_cast(buf); buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); } else if (kind() == K_BSD) { - assert(0 && "BSD archive format is not supported"); + llvm_unreachable("BSD archive format is not supported"); } else { uint32_t member_count = 0; uint32_t symbol_count = 0; @@ -348,7 +349,7 @@ Archive::symbol_iterator Archive::end_symbols() const { symbol_count = *reinterpret_cast(buf); buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); } else if (kind() == K_BSD) { - assert(0 && "BSD archive format is not supported"); + llvm_unreachable("BSD archive format is not supported"); } else { uint32_t member_count = 0; member_count = *reinterpret_cast(buf); -- cgit v1.2.3 From d04a8d4b33ff316ca4cf961e06c9e312eff8e64f Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Mon, 3 Dec 2012 16:50:05 +0000 Subject: Use the new script to sort the includes of every file under lib. Sooooo many of these had incorrect or strange main module includes. I have manually inspected all of these, and fixed the main module include to be the nearest plausible thing I could find. If you own or care about any of these source files, I encourage you to take some time and check that these edits were sensible. I can't have broken anything (I strictly added headers, and reordered them, never removed), but they may not be the headers you'd really like to identify as containing the API being implemented. Many forward declarations and missing includes were added to a header files to allow them to parse cleanly when included first. The main module rule does in fact have its merits. =] git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169131 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/Archive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Object/Archive.cpp') diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 5b1e007e85..dafcb72735 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -13,8 +13,8 @@ #include "llvm/Object/Archive.h" #include "llvm/ADT/APInt.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" using namespace llvm; -- cgit v1.2.3