return Ret;
}
+Archive::Child::Child(const Archive *Parent, StringRef Data,
+ uint16_t StartOfFile)
+ : Parent(Parent), Data(Data), StartOfFile(StartOfFile) {}
+
Archive::Child::Child(const Archive *Parent, const char *Start,
std::error_code *EC)
: Parent(Parent) {
Data = StringRef(Start, Size);
if (!isThinMember()) {
ErrorOr<uint64_t> MemberSize = getRawSize();
- if (MemberSize.getError()) {
- assert (EC && "Error must be caught");
- *EC = MemberSize.getError();
+ if ((*EC = MemberSize.getError()))
return;
- }
Size += MemberSize.get();
Data = StringRef(Start, Size);
}
StringRef Name = getRawName();
if (Name.startswith("#1/")) {
uint64_t NameSize;
- if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) {
- if (EC)
- *EC = object_error::parse_failed; // Long name offset is not an integer.
- return;
- }
+ if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize))
+ llvm_unreachable("Long name length is not an integer");
StartOfFile += NameSize;
}
}
-ErrorOr<std::unique_ptr<Archive::Child>> Archive::Child::create(
- const Archive *Parent, const char *Start) {
- std::error_code EC;
- std::unique_ptr<Archive::Child> Ret(new Archive::Child(Parent, Start, &EC));
- if (EC)
- return EC;
- return std::move(Ret);
-}
-
ErrorOr<uint64_t> Archive::Child::getSize() const {
if (Parent->IsThin) {
ErrorOr<uint32_t> Size = getHeader()->getSize();
ErrorOr<Archive::Child> Archive::Child::getNext() const {
size_t SpaceToSkip = Data.size();
// If it's odd, add 1 to make it even.
- size_t Pad = 0;
if (SpaceToSkip & 1)
- Pad++;
+ ++SpaceToSkip;
- const char *NextLoc = Data.data() + SpaceToSkip + Pad;
+ const char *NextLoc = Data.data() + SpaceToSkip;
// Check to see if this is at the end of the archive.
- if (NextLoc == Parent->Data.getBufferEnd() ||
- NextLoc == Parent->Data.getBufferEnd() - Pad )
+ if (NextLoc == Parent->Data.getBufferEnd())
return Child(Parent, nullptr, nullptr);
// Check to see if this is past the end of the archive.
if (NextLoc > Parent->Data.getBufferEnd())
return object_error::parse_failed;
- auto ChildOrErr = Child::create(Parent, NextLoc);
- if (std::error_code EC = ChildOrErr.getError())
+ std::error_code EC;
+ Child Ret(Parent, NextLoc, &EC);
+ if (EC)
return EC;
- return std::move(*ChildOrErr.get());
+ return Ret;
}
uint64_t Archive::Child::getChildOffset() const {
// Get the offset.
std::size_t offset;
if (name.substr(1).rtrim(" ").getAsInteger(10, offset))
- return object_error::parse_failed; // Long name offset is not an integer.
- // Check for bad stringtable iterator.
- if (std::error_code EC = Parent->StringTable->getError())
- return EC;
- const char *addr = (*Parent->StringTable)->Data.begin()
- + sizeof(ArchiveMemberHeader)
- + offset;
+ llvm_unreachable("Long name offset is not an integer");
+
// Verify it.
- auto Size = (*Parent->StringTable)->getSize();
- if (std::error_code EC = Size.getError())
- return EC;
- if (Parent->StringTable == Parent->child_end()
- || addr < ((*Parent->StringTable)->Data.begin()
- + sizeof(ArchiveMemberHeader))
- || addr > ((*Parent->StringTable)->Data.begin()
- + sizeof(ArchiveMemberHeader)
- + Size.get()))
+ if (offset >= Parent->StringTable.size())
return object_error::parse_failed;
+ const char *addr = Parent->StringTable.begin() + offset;
// GNU long file names end with a "/\n".
if (Parent->kind() == K_GNU || Parent->kind() == K_MIPS64) {
} else if (name.startswith("#1/")) {
uint64_t name_size;
if (name.substr(3).rtrim(" ").getAsInteger(10, name_size))
- return object_error::parse_failed; // Long name offset is not an integer.
+ llvm_unreachable("Long name length is not an ingeter");
return Data.substr(sizeof(ArchiveMemberHeader), name_size)
.rtrim(StringRef("\0", 1));
}
return std::move(Ret);
}
+void Archive::setFirstRegular(const Child &C) {
+ FirstRegularData = C.Data;
+ FirstRegularStartOfFile = C.StartOfFile;
+}
+
Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
- : Binary(Binary::ID_Archive, Source), SymbolTable(child_end()),
- StringTable(child_end()), FirstRegular(child_end()) {
+ : Binary(Binary::ID_Archive, Source) {
StringRef Buffer = Data.getBuffer();
// Check for sufficient magic.
if (Buffer.startswith(ThinMagic)) {
}
// Get the special members.
- child_iterator i = child_begin(false);
- child_iterator e = child_end();
+ child_iterator I = child_begin(false);
+ if ((ec = I->getError()))
+ return;
+ child_iterator E = child_end();
- if (!*i || i == e) {
- ec = i->getError();
+ if (I == E) {
+ ec = std::error_code();
return;
}
+ const Child *C = &**I;
+
+ auto Increment = [&]() {
+ ++I;
+ if ((ec = I->getError()))
+ return true;
+ C = &**I;
+ return false;
+ };
- StringRef Name = (*i)->getRawName();
+ StringRef Name = C->getRawName();
// Below is the pattern that is used to figure out the archive format
// GNU archive format
if (Name == "__.SYMDEF") {
Format = K_BSD;
- SymbolTable = i;
- ++i;
- if (!*i) {
- ec = i->getError();
+ // We know that the symbol table is not an external file, so we just assert
+ // there is no error.
+ SymbolTable = *C->getBuffer();
+ if (Increment())
return;
- }
+ setFirstRegular(*C);
- FirstRegular = i;
ec = std::error_code();
return;
}
if (Name.startswith("#1/")) {
Format = K_BSD;
// We know this is BSD, so getName will work since there is no string table.
- ErrorOr<StringRef> NameOrErr = (*i)->getName();
+ ErrorOr<StringRef> NameOrErr = C->getName();
ec = NameOrErr.getError();
if (ec)
return;
Name = NameOrErr.get();
if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
- SymbolTable = i;
- ++i;
- if (!*i) {
- ec = i->getError();
+ // We know that the symbol table is not an external file, so we just
+ // assert there is no error.
+ SymbolTable = *C->getBuffer();
+ if (Increment())
return;
- }
}
- FirstRegular = i;
+ setFirstRegular(*C);
return;
}
bool has64SymTable = false;
if (Name == "/" || Name == "/SYM64/") {
- SymbolTable = i;
+ // We know that the symbol table is not an external file, so we just assert
+ // there is no error.
+ SymbolTable = *C->getBuffer();
if (Name == "/SYM64/")
has64SymTable = true;
- ++i;
- if (!*i || i == e) {
- ec = i->getError();
+ if (Increment())
+ return;
+ if (I == E) {
+ ec = std::error_code();
return;
}
- Name = (*i)->getRawName();
+ Name = C->getRawName();
}
if (Name == "//") {
Format = has64SymTable ? K_MIPS64 : K_GNU;
- StringTable = i;
- ++i;
- if (!*i) {
- ec = i->getError();
+ // The string table is never an external member, so we just assert on the
+ // ErrorOr.
+ StringTable = *C->getBuffer();
+ if (Increment())
return;
- }
- FirstRegular = i;
+ setFirstRegular(*C);
ec = std::error_code();
return;
}
if (Name[0] != '/') {
Format = has64SymTable ? K_MIPS64 : K_GNU;
- FirstRegular = i;
+ setFirstRegular(*C);
ec = std::error_code();
return;
}
}
Format = K_COFF;
- SymbolTable = i;
+ // We know that the symbol table is not an external file, so we just assert
+ // there is no error.
+ SymbolTable = *C->getBuffer();
- ++i;
- if (!*i) {
- ec = i->getError();
+ if (Increment())
return;
- }
- if (i == e) {
- FirstRegular = i;
+
+ if (I == E) {
+ setFirstRegular(*C);
ec = std::error_code();
return;
}
- Name = (*i)->getRawName();
+ Name = C->getRawName();
if (Name == "//") {
- StringTable = i;
- ++i;
- if (!*i) {
- ec = i->getError();
+ // The string table is never an external member, so we just assert on the
+ // ErrorOr.
+ StringTable = *C->getBuffer();
+ if (Increment())
return;
- }
}
- FirstRegular = i;
+ setFirstRegular(*C);
ec = std::error_code();
}
return child_end();
if (SkipInternal)
- return FirstRegular;
+ return Child(this, FirstRegularData, FirstRegularStartOfFile);
const char *Loc = Data.getBufferStart() + strlen(Magic);
- auto ChildOrErr = Child::create(this, Loc);
- if (std::error_code EC = ChildOrErr.getError())
+ std::error_code EC;
+ Child c(this, Loc, &EC);
+ if (EC)
return child_iterator(EC);
- Child c = *(ChildOrErr.get());
return child_iterator(c);
}
Archive::child_iterator Archive::child_end() const {
- // This with a second argument of nullptr can't return an Error.
- auto ChildOrErr = Child::create(this, nullptr);
- if (ChildOrErr.getError())
- llvm_unreachable("Can't create Archive::child_end().");
- Child c = *(ChildOrErr.get());
- return child_iterator(c);
+ return Child(this, nullptr, nullptr);
}
StringRef Archive::Symbol::getName() const {
return Parent->getSymbolTable().begin() + StringIndex;
}
-ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const {
+ErrorOr<Archive::Child> Archive::Symbol::getMember() const {
const char *Buf = Parent->getSymbolTable().begin();
const char *Offsets = Buf;
if (Parent->kind() == K_MIPS64)
}
const char *Loc = Parent->getData().begin() + Offset;
- auto ChildOrErr = Child::create(Parent, Loc);
- if (std::error_code EC = ChildOrErr.getError())
+ std::error_code EC;
+ Child C(Parent, Loc, &EC);
+ if (EC)
return EC;
- child_iterator Iter(std::move(*ChildOrErr.get()));
- return Iter;
+ return C;
}
Archive::Symbol Archive::Symbol::getNext() const {
return child_end();
}
-bool Archive::hasSymbolTable() const {
- return SymbolTable != child_end();
-}
+bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }