X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FObject%2FArchive.cpp;h=45156f1311e9fbe987afd73d81c4e2854b659162;hb=84cab94cbb6c99327075c893502438b1ef95e168;hp=c6cf219c09bf5b33a0b04ea32db920964e174f86;hpb=4172a8abbabea2359d91bb07101166565127d798;p=oota-llvm.git diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index c6cf219c09b..45156f1311e 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -110,23 +110,19 @@ 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, NULL); + return Child(Parent, nullptr); return Child(Parent, NextLoc); } -error_code Archive::Child::getName(StringRef &Result) const { +ErrorOr Archive::Child::getName() const { StringRef name = getRawName(); // Check if it's a special name. if (name[0] == '/') { - if (name.size() == 1) { // Linker member. - Result = name; - return object_error::success; - } - if (name.size() == 2 && name[1] == '/') { // String table. - Result = name; - return object_error::success; - } + if (name.size() == 1) // Linker member. + return name; + if (name.size() == 2 && name[1] == '/') // String table. + return name; // It's a long name. // Get the offset. std::size_t offset; @@ -136,7 +132,7 @@ error_code Archive::Child::getName(StringRef &Result) const { + sizeof(ArchiveMemberHeader) + offset; // Verify it. - if (Parent->StringTable == Parent->end_children() + if (Parent->StringTable == Parent->child_end() || addr < (Parent->StringTable->Data.begin() + sizeof(ArchiveMemberHeader)) || addr > (Parent->StringTable->Data.begin() @@ -147,65 +143,68 @@ error_code Archive::Child::getName(StringRef &Result) const { // 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 StringRef(addr, End); } - return object_error::success; + return StringRef(addr); } else if (name.startswith("#1/")) { 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) + return Data.substr(sizeof(ArchiveMemberHeader), name_size) .rtrim(StringRef("\0", 1)); - return object_error::success; } // It's a simple name. if (name[name.size() - 1] == '/') - Result = name.substr(0, name.size() - 1); - else - Result = name; - return object_error::success; + return name.substr(0, name.size() - 1); + return name; } -error_code Archive::Child::getMemoryBuffer(OwningPtr &Result, - bool FullPath) const { - StringRef Name; - if (error_code ec = getName(Name)) - return ec; +ErrorOr> +Archive::Child::getMemoryBuffer(bool FullPath) const { + ErrorOr NameOrErr = getName(); + if (std::error_code EC = NameOrErr.getError()) + return EC; + StringRef Name = NameOrErr.get(); SmallString<128> Path; - Result.reset(MemoryBuffer::getMemBuffer( - getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name + ")") - .toStringRef(Path) - : Name, + std::unique_ptr Ret(MemoryBuffer::getMemBuffer( + getBuffer(), + FullPath + ? (Twine(Parent->getFileName()) + "(" + Name + ")").toStringRef(Path) + : Name, false)); - return error_code::success(); + return std::move(Ret); } -error_code Archive::Child::getAsBinary(OwningPtr &Result) const { - OwningPtr ret; - OwningPtr Buff; - if (error_code ec = getMemoryBuffer(Buff)) - return ec; - if (error_code ec = createBinary(Buff.take(), ret)) - return ec; - Result.swap(ret); - return object_error::success; +ErrorOr> +Archive::Child::getAsBinary(LLVMContext *Context) const { + ErrorOr> BuffOrErr = getMemoryBuffer(); + if (std::error_code EC = BuffOrErr.getError()) + return EC; + + return createBinary(std::move(*BuffOrErr), Context); } -Archive::Archive(MemoryBuffer *source, error_code &ec) - : Binary(Binary::ID_Archive, source), SymbolTable(end_children()) { +ErrorOr> +Archive::create(std::unique_ptr Source) { + std::error_code EC; + std::unique_ptr Ret(new Archive(std::move(Source), EC)); + if (EC) + return EC; + return std::move(Ret); +} + +Archive::Archive(std::unique_ptr Source, std::error_code &ec) + : Binary(Binary::ID_Archive, std::move(Source)), SymbolTable(child_end()) { // Check for sufficient magic. - assert(source); - if (source->getBufferSize() < 8 || - StringRef(source->getBufferStart(), 8) != Magic) { + if (Data->getBufferSize() < 8 || + StringRef(Data->getBufferStart(), 8) != Magic) { ec = object_error::invalid_file_type; return; } // Get the special members. - child_iterator i = begin_children(false); - child_iterator e = end_children(); + child_iterator i = child_begin(false); + child_iterator e = child_end(); if (i == e) { ec = object_error::success; @@ -245,9 +244,11 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) 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); + ErrorOr NameOrErr = i->getName(); + ec = NameOrErr.getError(); if (ec) return; + Name = NameOrErr.get(); if (Name == "__.SYMDEF SORTED") { SymbolTable = i; ++i; @@ -309,9 +310,9 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) ec = object_error::success; } -Archive::child_iterator Archive::begin_children(bool SkipInternal) const { +Archive::child_iterator Archive::child_begin(bool SkipInternal) const { if (Data->getBufferSize() == 8) // empty archive. - return end_children(); + return child_end(); if (SkipInternal) return FirstRegular; @@ -321,16 +322,15 @@ Archive::child_iterator Archive::begin_children(bool SkipInternal) const { return c; } -Archive::child_iterator Archive::end_children() const { - return Child(this, NULL); +Archive::child_iterator Archive::child_end() const { + return Child(this, nullptr); } -error_code Archive::Symbol::getName(StringRef &Result) const { - Result = StringRef(Parent->SymbolTable->getBuffer().begin() + StringIndex); - return object_error::success; +StringRef Archive::Symbol::getName() const { + return Parent->SymbolTable->getBuffer().begin() + StringIndex; } -error_code Archive::Symbol::getMember(child_iterator &Result) const { +ErrorOr Archive::Symbol::getMember() const { const char *Buf = Parent->SymbolTable->getBuffer().begin(); const char *Offsets = Buf + 4; uint32_t Offset = 0; @@ -338,7 +338,14 @@ error_code Archive::Symbol::getMember(child_iterator &Result) const { Offset = *(reinterpret_cast(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(Offsets) + + (SymbolIndex * 2) + 1); } else { uint32_t MemberCount = *reinterpret_cast(Buf); @@ -370,22 +377,55 @@ error_code Archive::Symbol::getMember(child_iterator &Result) const { } const char *Loc = Parent->getData().begin() + Offset; - Result = Child(Parent, Loc); - - return object_error::success; + child_iterator Iter(Child(Parent, Loc)); + return Iter; } 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(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(Ranlibs) + + (t.SymbolIndex * 2)); + NextRanStrx = *(reinterpret_cast(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; } -Archive::symbol_iterator Archive::begin_symbols() const { - if (SymbolTable == end_children()) +Archive::symbol_iterator Archive::symbol_begin() const { + if (!hasSymbolTable()) return symbol_iterator(Symbol(this, 0, 0)); const char *buf = SymbolTable->getBuffer().begin(); @@ -394,7 +434,22 @@ 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) { - 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(buf)) / + (sizeof(uint32_t) * 2); + const char *ranlibs = buf + 4; + uint32_t ran_strx = 0; + ran_strx = *(reinterpret_cast(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; @@ -407,8 +462,8 @@ Archive::symbol_iterator Archive::begin_symbols() const { return symbol_iterator(Symbol(this, 0, string_start_offset)); } -Archive::symbol_iterator Archive::end_symbols() const { - if (SymbolTable == end_children()) +Archive::symbol_iterator Archive::symbol_end() const { + if (!hasSymbolTable()) return symbol_iterator(Symbol(this, 0, 0)); const char *buf = SymbolTable->getBuffer().begin(); @@ -416,7 +471,8 @@ Archive::symbol_iterator Archive::end_symbols() const { if (kind() == K_GNU) { symbol_count = *reinterpret_cast(buf); } else if (kind() == K_BSD) { - llvm_unreachable("BSD archive format is not supported"); + symbol_count = (*reinterpret_cast(buf)) / + (sizeof(uint32_t) * 2); } else { uint32_t member_count = 0; member_count = *reinterpret_cast(buf); @@ -428,19 +484,22 @@ Archive::symbol_iterator Archive::end_symbols() const { } 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; + Archive::symbol_iterator bs = symbol_begin(); + Archive::symbol_iterator es = symbol_end(); + for (; bs != es; ++bs) { - if (bs->getName(symname)) - return end_children(); - if (symname == name) { - if (bs->getMember(result)) - return end_children(); - return result; + StringRef SymName = bs->getName(); + if (SymName == name) { + ErrorOr ResultOrErr = bs->getMember(); + // FIXME: Should we really eat the error? + if (ResultOrErr.getError()) + return child_end(); + return ResultOrErr.get(); } } - return end_children(); + return child_end(); +} + +bool Archive::hasSymbolTable() const { + return SymbolTable != child_end(); }