#include "llvm/ADT/Twine.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
using namespace llvm;
using namespace object;
if (!Start)
return;
- const ArchiveMemberHeader *Header =
- reinterpret_cast<const ArchiveMemberHeader *>(Start);
uint64_t Size = sizeof(ArchiveMemberHeader);
- if (!Parent->IsThin || Header->getName() == "/" || Header->getName() == "//")
- Size += Header->getSize();
Data = StringRef(Start, Size);
+ if (!isThinMember()) {
+ Size += getRawSize();
+ Data = StringRef(Start, Size);
+ }
// Setup StartOfFile and PaddingBytes.
StartOfFile = sizeof(ArchiveMemberHeader);
// Don't include attached name.
- StringRef Name = Header->getName();
+ StringRef Name = getRawName();
if (Name.startswith("#1/")) {
uint64_t NameSize;
if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize))
return getHeader()->getSize();
}
+bool Archive::Child::isThinMember() const {
+ StringRef Name = getHeader()->getName();
+ return Parent->IsThin && Name != "/" && Name != "//";
+}
+
+ErrorOr<StringRef> Archive::Child::getBuffer() const {
+ if (!isThinMember())
+ return StringRef(Data.data() + StartOfFile, getSize());
+ ErrorOr<StringRef> Name = getName();
+ if (std::error_code EC = Name.getError())
+ return EC;
+ SmallString<128> FullName = sys::path::parent_path(
+ Parent->getMemoryBufferRef().getBufferIdentifier());
+ sys::path::append(FullName, *Name);
+ ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName);
+ if (std::error_code EC = Buf.getError())
+ return EC;
+ Parent->ThinBuffers.push_back(std::move(*Buf));
+ return Parent->ThinBuffers.back()->getBuffer();
+}
+
Archive::Child Archive::Child::getNext() const {
size_t SpaceToSkip = Data.size();
// If it's odd, add 1 to make it even.
if (std::error_code EC = NameOrErr.getError())
return EC;
StringRef Name = NameOrErr.get();
- return MemoryBufferRef(getBuffer(), Name);
+ ErrorOr<StringRef> Buf = getBuffer();
+ if (std::error_code EC = Buf.getError())
+ return EC;
+ return MemoryBufferRef(*Buf, Name);
}
ErrorOr<std::unique_ptr<Binary>>
}
StringRef Archive::Symbol::getName() const {
- return Parent->SymbolTable->getBuffer().begin() + StringIndex;
+ return Parent->getSymbolTable().begin() + StringIndex;
}
ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const {
- const char *Buf = Parent->SymbolTable->getBuffer().begin();
+ const char *Buf = Parent->getSymbolTable().begin();
const char *Offsets = Buf;
if (Parent->kind() == K_MIPS64)
Offsets += sizeof(uint64_t);
// 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();
+ const char *Buf = Parent->getSymbolTable().begin();
uint32_t RanlibCount = 0;
RanlibCount = read32le(Buf) / 8;
// If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount)
}
} else {
// Go to one past next null.
- t.StringIndex =
- Parent->SymbolTable->getBuffer().find('\0', t.StringIndex) + 1;
+ t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1;
}
++t.SymbolIndex;
return t;
if (!hasSymbolTable())
return symbol_iterator(Symbol(this, 0, 0));
- const char *buf = SymbolTable->getBuffer().begin();
+ const char *buf = getSymbolTable().begin();
if (kind() == K_GNU) {
uint32_t symbol_count = 0;
symbol_count = read32be(buf);
symbol_count = read32le(buf);
buf += 4 + (symbol_count * 2); // Skip indices.
}
- uint32_t string_start_offset = buf - SymbolTable->getBuffer().begin();
+ uint32_t string_start_offset = buf - getSymbolTable().begin();
return symbol_iterator(Symbol(this, 0, string_start_offset));
}
}
uint32_t Archive::getNumberOfSymbols() const {
- const char *buf = SymbolTable->getBuffer().begin();
+ const char *buf = getSymbolTable().begin();
if (kind() == K_GNU)
return read32be(buf);
if (kind() == K_MIPS64)