X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FObject%2FArchive.cpp;h=60c6d21f48237484e2b1493f1d04909844c2ec45;hb=71857ccdb83b6374f7a791c2dae45ce9934a85af;hp=5585bc44f7e7141fd63f5d934ef907cf27d7ad87;hpb=5263d0aa6a0227ccd9ed8062c84b294137e88a68;p=oota-llvm.git diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 5585bc44f7e..60c6d21f482 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -54,20 +54,61 @@ StringRef ArchiveMemberHeader::getName() const { return llvm::StringRef(Name, end); } -uint64_t ArchiveMemberHeader::getSize() const { - uint64_t ret; - if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, ret)) - llvm_unreachable("Size is not an integer."); - return ret; +uint32_t ArchiveMemberHeader::getSize() const { + uint32_t Ret; + if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, Ret)) + llvm_unreachable("Size is not a decimal number."); + return Ret; } -Archive::Child::Child(const Archive *p, StringRef d) : Parent(p), Data(d) { - if (!p || d.empty()) +sys::fs::perms ArchiveMemberHeader::getAccessMode() const { + unsigned Ret; + if (StringRef(AccessMode, sizeof(AccessMode)).rtrim(" ").getAsInteger(8, Ret)) + llvm_unreachable("Access mode is not an octal number."); + return static_cast(Ret); +} + +sys::TimeValue ArchiveMemberHeader::getLastModified() const { + unsigned Seconds; + if (StringRef(LastModified, sizeof(LastModified)).rtrim(" ") + .getAsInteger(10, Seconds)) + llvm_unreachable("Last modified time not a decimal number."); + + sys::TimeValue Ret; + Ret.fromEpochTime(Seconds); + return Ret; +} + +unsigned ArchiveMemberHeader::getUID() const { + unsigned Ret; + if (StringRef(UID, sizeof(UID)).rtrim(" ").getAsInteger(10, Ret)) + llvm_unreachable("UID time not a decimal number."); + return Ret; +} + +unsigned ArchiveMemberHeader::getGID() const { + unsigned Ret; + if (StringRef(GID, sizeof(GID)).rtrim(" ").getAsInteger(10, Ret)) + llvm_unreachable("GID time not a decimal number."); + 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); + Data = StringRef(Start, sizeof(ArchiveMemberHeader) + Header->getSize()); + // Setup StartOfFile and PaddingBytes. StartOfFile = sizeof(ArchiveMemberHeader); // Don't include attached name. - StringRef Name = ToHeader(Data.data())->getName(); + StringRef Name = Header->getName(); if (Name.startswith("#1/")) { uint64_t NameSize; if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) @@ -86,11 +127,9 @@ Archive::Child Archive::Child::getNext() const { // Check to see if this is past the end of the archive. if (NextLoc >= Parent->Data->getBufferEnd()) - return Child(Parent, StringRef(0, 0)); - - size_t NextSize = sizeof(ArchiveMemberHeader) + ToHeader(NextLoc)->getSize(); + return Child(Parent, NULL); - return Child(Parent, StringRef(NextLoc, NextSize)); + return Child(Parent, NextLoc); } error_code Archive::Child::getName(StringRef &Result) const { @@ -171,7 +210,7 @@ error_code Archive::Child::getAsBinary(OwningPtr &Result) const { } 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. @@ -197,9 +236,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 : / @@ -217,6 +256,17 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) 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 == StringRef("__.SYMDEF SORTED\0\0\0", 20)) + SymbolTable = i; + return; + } + if (Name == "/") { SymbolTable = i; @@ -265,17 +315,15 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) Archive::child_iterator Archive::begin_children(bool skip_internal) const { const char *Loc = Data->getBufferStart() + strlen(Magic); - size_t Size = sizeof(ArchiveMemberHeader) + - ToHeader(Loc)->getSize(); - Child c(this, StringRef(Loc, Size)); + Child c(this, Loc); // Skip internals at the beginning of an archive. - if (skip_internal && isInternalMember(*ToHeader(Loc))) + if (skip_internal && isInternalMember(*toHeader(Loc))) return c.getNext(); return c; } Archive::child_iterator Archive::end_children() const { - return Child(this, StringRef(0, 0)); + return Child(this, NULL); } error_code Archive::Symbol::getName(StringRef &Result) const { @@ -323,9 +371,7 @@ error_code Archive::Symbol::getMember(child_iterator &Result) const { } const char *Loc = Parent->getData().begin() + Offset; - size_t Size = sizeof(ArchiveMemberHeader) + - ToHeader(Loc)->getSize(); - Result = Child(Parent, StringRef(Loc, Size)); + Result = Child(Parent, Loc); return object_error::success; } @@ -340,6 +386,9 @@ Archive::Symbol Archive::Symbol::getNext() const { } Archive::symbol_iterator Archive::begin_symbols() const { + if (SymbolTable == end_children()) + return symbol_iterator(Symbol(this, 0, 0)); + const char *buf = SymbolTable->getBuffer().begin(); if (kind() == K_GNU) { uint32_t symbol_count = 0; @@ -360,6 +409,9 @@ Archive::symbol_iterator Archive::begin_symbols() const { } Archive::symbol_iterator Archive::end_symbols() const { + if (SymbolTable == end_children()) + return symbol_iterator(Symbol(this, 0, 0)); + const char *buf = SymbolTable->getBuffer().begin(); uint32_t symbol_count = 0; if (kind() == K_GNU) {