X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FObject%2FArchive.cpp;h=f91752e0ab0c9f192e22a91b24e74de9951d9eb4;hb=3767c7446edea95277509477a9bb3048ef2e0b95;hp=292d50a17633a2f2c1da64a920f00a23b34f6e02;hpb=9941bdd1fec00aa7a72117d2c2e21724c275e89a;p=oota-llvm.git diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 292d50a1763..f91752e0ab0 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -21,21 +21,7 @@ using namespace llvm; using namespace object; -static const char *Magic = "!\n"; - -static bool isInternalMember(const ArchiveMemberHeader &amh) { - static const char *const internals[] = { - "/", - "//" - }; - - StringRef name = amh.getName(); - for (std::size_t i = 0; i < sizeof(internals) / sizeof(*internals); ++i) { - if (name == internals[i]) - return true; - } - return false; -} +static const char *const Magic = "!\n"; void Archive::anchor() { } @@ -93,16 +79,13 @@ unsigned ArchiveMemberHeader::getGID() const { return Ret; } -static const ArchiveMemberHeader *toHeader(const char *base) { - return reinterpret_cast(base); -} - Archive::Child::Child(const Archive *Parent, const char *Start) : Parent(Parent) { if (!Start) return; - const ArchiveMemberHeader *Header = toHeader(Start); + const ArchiveMemberHeader *Header = + reinterpret_cast(Start); Data = StringRef(Start, sizeof(ArchiveMemberHeader) + Header->getSize()); // Setup StartOfFile and PaddingBytes. @@ -173,7 +156,8 @@ error_code Archive::Child::getName(StringRef &Result) const { uint64_t name_size; if (name.substr(3).rtrim(" ").getAsInteger(10, name_size)) llvm_unreachable("Long name length is not an ingeter"); - Result = Data.substr(sizeof(ArchiveMemberHeader), name_size); + Result = Data.substr(sizeof(ArchiveMemberHeader), name_size) + .rtrim(StringRef("\0", 1)); return object_error::success; } // It's a simple name. @@ -203,18 +187,19 @@ error_code Archive::Child::getAsBinary(OwningPtr &Result) const { OwningPtr Buff; if (error_code ec = getMemoryBuffer(Buff)) return ec; - if (error_code ec = createBinary(Buff.take(), ret)) - return ec; - Result.swap(ret); + ErrorOr BinaryOrErr = createBinary(Buff.take()); + if (error_code EC = BinaryOrErr.getError()) + return EC; + Result.reset(BinaryOrErr.get()); return object_error::success; } Archive::Archive(MemoryBuffer *source, error_code &ec) - : Binary(Binary::ID_Archive, source) { + : Binary(Binary::ID_Archive, source), SymbolTable(end_children()) { // Check for sufficient magic. - if (!source || source->getBufferSize() - < (8 + sizeof(ArchiveMemberHeader)) // Smallest archive. - || StringRef(source->getBufferStart(), 8) != Magic) { + assert(source); + if (source->getBufferSize() < 8 || + StringRef(source->getBufferStart(), 8) != Magic) { ec = object_error::invalid_file_type; return; } @@ -224,7 +209,7 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) child_iterator e = end_children(); if (i == e) { - ec = object_error::parse_failed; + ec = object_error::success; return; } @@ -236,9 +221,9 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) // 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 + // First member : __.SYMDEF or "__.SYMDEF SORTED" (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 : / @@ -252,10 +237,26 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) if (Name == "__.SYMDEF") { Format = K_BSD; SymbolTable = i; + ++i; + FirstRegular = i; ec = object_error::success; return; } + if (Name.startswith("#1/")) { + Format = K_BSD; + // We know this is BSD, so getName will work since there is no string table. + ec = i->getName(Name); + if (ec) + return; + if (Name == "__.SYMDEF SORTED") { + SymbolTable = i; + ++i; + } + FirstRegular = i; + return; + } + if (Name == "/") { SymbolTable = i; @@ -270,12 +271,15 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) if (Name == "//") { Format = K_GNU; StringTable = i; + ++i; + FirstRegular = i; ec = object_error::success; return; } if (Name[0] != '/') { Format = K_GNU; + FirstRegular = i; ec = object_error::success; return; } @@ -290,24 +294,31 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) ++i; if (i == e) { + FirstRegular = i; ec = object_error::success; return; } Name = i->getRawName(); - if (Name == "//") + if (Name == "//") { StringTable = i; + ++i; + } + FirstRegular = i; ec = object_error::success; } -Archive::child_iterator Archive::begin_children(bool skip_internal) const { +Archive::child_iterator Archive::begin_children(bool SkipInternal) const { + if (Data->getBufferSize() == 8) // empty archive. + return end_children(); + + if (SkipInternal) + return FirstRegular; + const char *Loc = Data->getBufferStart() + strlen(Magic); Child c(this, Loc); - // Skip internals at the beginning of an archive. - if (skip_internal && isInternalMember(*toHeader(Loc))) - return c.getNext(); return c; } @@ -375,6 +386,9 @@ Archive::Symbol Archive::Symbol::getNext() const { } Archive::symbol_iterator Archive::begin_symbols() const { + if (!hasSymbolTable()) + return symbol_iterator(Symbol(this, 0, 0)); + const char *buf = SymbolTable->getBuffer().begin(); if (kind() == K_GNU) { uint32_t symbol_count = 0; @@ -395,6 +409,9 @@ Archive::symbol_iterator Archive::begin_symbols() const { } Archive::symbol_iterator Archive::end_symbols() const { + if (!hasSymbolTable()) + return symbol_iterator(Symbol(this, 0, 0)); + const char *buf = SymbolTable->getBuffer().begin(); uint32_t symbol_count = 0; if (kind() == K_GNU) { @@ -428,3 +445,7 @@ Archive::child_iterator Archive::findSym(StringRef name) const { } return end_children(); } + +bool Archive::hasSymbolTable() const { + return SymbolTable != end_children(); +}