aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/Archive.cpp
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2022-01-18 12:41:45 +0000
committerFlorian Hahn <flo@fhahn.com>2022-01-18 12:44:16 +0000
commit1b9d323a266c9cc125e1993be56db97d71f25d39 (patch)
treea2ba481b63b9673293c9923662457453f68aee4e /llvm/lib/Object/Archive.cpp
parente781620dee4415018bdf3769a97c2ec31a85ff68 (diff)
downloadllvm-1b9d323a266c9cc125e1993be56db97d71f25d39.zip
llvm-1b9d323a266c9cc125e1993be56db97d71f25d39.tar.gz
llvm-1b9d323a266c9cc125e1993be56db97d71f25d39.tar.bz2
Revert "[AIX] Support of Big archive (read)"
This appears to be causing the following build failures on green dragon during stage2 builds on macOS: /System/Volumes/Data/jenkins/workspace/apple-clang-stage2-configure-RA_osceola/clang.roots/BuildRecords/clang-9999.99_install/Objects/obj-llvm/./bin/clang++ -fno-stack-protector -fno-common -Wno-profile-instr-unprofiled -Wno-unknown-warning-option -Werror=unguarded-availability-new -fPIC -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -fmodules -fmodules-cache-path=/System/Volumes/Data/jenkins/workspace/apple-clang-stage2-configure-RA_osceola/clang.roots/BuildRecords/clang-9999.99_install/Objects/obj-llvm/tools/clang/stage2-bins/module.cache -fcxx-modules -Xclang -fmodules-local-submodule-visibility -gmodules -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-class-memaccess -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -fdiagnostics-color -O2 -gline-tables-only -DNDEBUG -arch x86_64 -arch arm64 -arch arm64e -isysroot /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk -mmacosx-version-min=10.10 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -Wl,-dead_strip tools/llvm-cov/CMakeFiles/llvm-cov.dir/llvm-cov.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/gcov.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/CodeCoverage.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/CoverageExporterJson.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/CoverageExporterLcov.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/CoverageFilters.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/CoverageReport.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/CoverageSummaryInfo.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/SourceCoverageView.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/SourceCoverageViewHTML.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/SourceCoverageViewText.cpp.o tools/llvm-cov/CMakeFiles/llvm-cov.dir/TestingSupport.cpp.o -o bin/llvm-cov -Wl,-rpath,@loader_path/../lib lib/libLLVMCore.a lib/libLLVMSupport.a lib/libLLVMObject.a lib/libLLVMCoverage.a lib/libLLVMProfileData.a lib/libLLVMDebugInfoDWARF.a lib/libLLVMObject.a lib/libLLVMBitReader.a lib/libLLVMCore.a lib/libLLVMRemarks.a lib/libLLVMBitstreamReader.a lib/libLLVMMCParser.a lib/libLLVMTextAPI.a lib/libLLVMMC.a lib/libLLVMBinaryFormat.a lib/libLLVMDebugInfoCodeView.a lib/libLLVMSupport.a -lm /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk/usr/lib/libz.tbd /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk/usr/lib/libcurses.tbd lib/libLLVMDemangle.a && cd /System/Volumes/Data/jenkins/workspace/apple-clang-stage2-configure-RA_osceola/clang.roots/BuildRecords/clang-9999.99_install/Objects/obj-llvm/tools/clang/stage2-bins/tools/llvm-cov && xcrun dsymutil -o=llvm-cov.dSYM /System/Volumes/Data/jenkins/workspace/apple-clang-stage2-configure-RA_osceola/clang.roots/BuildRecords/clang-9999.99_install/Objects/obj-llvm/tools/clang/stage2-bins/bin/llvm-cov Undefined symbols for architecture x86_64: "llvm::object::CommonArchiveMemberHeader<llvm::object::BigArMemHdrType>::getRawAccessMode() const", referenced from: vtable for llvm::object::BigArchiveMemberHeader in libLLVMObject.a(Archive.cpp.o) "llvm::object::CommonArchiveMemberHeader<llvm::object::BigArMemHdrType>::getRawUID() const", referenced from: vtable for llvm::object::BigArchiveMemberHeader in libLLVMObject.a(Archive.cpp.o) "llvm::object::CommonArchiveMemberHeader<llvm::object::BigArMemHdrType>::getRawGID() const", referenced from: vtable for llvm::object::BigArchiveMemberHeader in libLLVMObject.a(Archive.cpp.o) "llvm::object::CommonArchiveMemberHeader<llvm::object::UnixArMemHdrType>::getRawAccessMode() const", referenced from: vtable for llvm::object::ArchiveMemberHeader in libLLVMObject.a(Archive.cpp.o) "llvm::object::CommonArchiveMemberHeader<llvm::object::UnixArMemHdrType>::getRawLastModified() const", referenced from: vtable for llvm::object::ArchiveMemberHeader in libLLVMObject.a(Archive.cpp.o) "llvm::object::CommonArchiveMemberHeader<llvm::object::BigArMemHdrType>::getRawLastModified() const", referenced from: vtable for llvm::object::BigArchiveMemberHeader in libLLVMObject.a(Archive.cpp.o) "llvm::object::CommonArchiveMemberHeader<llvm::object::BigArMemHdrType>::getOffset() const", referenced from: vtable for llvm::object::BigArchiveMemberHeader in libLLVMObject.a(Archive.cpp.o) "llvm::object::CommonArchiveMemberHeader<llvm::object::UnixArMemHdrType>::getRawUID() const", referenced from: vtable for llvm::object::ArchiveMemberHeader in libLLVMObject.a(Archive.cpp.o) "llvm::object::CommonArchiveMemberHeader<llvm::object::UnixArMemHdrType>::getRawGID() const", referenced from: vtable for llvm::object::ArchiveMemberHeader in libLLVMObject.a(Archive.cpp.o) "llvm::object::CommonArchiveMemberHeader<llvm::object::UnixArMemHdrType>::getOffset() const", referenced from: vtable for llvm::object::ArchiveMemberHeader in libLLVMObject.a(Archive.cpp.o) ld: symbol(s) not found for architecture x86_64 https://smooshbase.apple.com/ci/job/apple-clang-stage2-configure-RA_osceola/30276/console
Diffstat (limited to 'llvm/lib/Object/Archive.cpp')
-rw-r--r--llvm/lib/Object/Archive.cpp465
1 files changed, 146 insertions, 319 deletions
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
index 35cba1a..5492692 100644
--- a/llvm/lib/Object/Archive.cpp
+++ b/llvm/lib/Object/Archive.cpp
@@ -22,7 +22,6 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -39,6 +38,9 @@ using namespace llvm;
using namespace object;
using namespace llvm::support::endian;
+const char Magic[] = "!<arch>\n";
+const char ThinMagic[] = "!<thin>\n";
+
void Archive::anchor() {}
static Error malformedError(Twine Msg) {
@@ -47,59 +49,27 @@ static Error malformedError(Twine Msg) {
object_error::parse_failed);
}
-static Error
-createMemberHeaderParseError(const AbstractArchiveMemberHeader *ArMemHeader,
- const char *RawHeaderPtr, uint64_t Size) {
- StringRef Msg("remaining size of archive too small for next archive "
- "member header ");
-
- Expected<StringRef> NameOrErr = ArMemHeader->getName(Size);
- if (NameOrErr)
- return malformedError(Msg + "for " + *NameOrErr);
-
- consumeError(NameOrErr.takeError());
- uint64_t Offset = RawHeaderPtr - ArMemHeader->Parent->getData().data();
- return malformedError(Msg + "at offset " + Twine(Offset));
-}
-
-template <class T, std::size_t N>
-StringRef getFieldRawString(const T (&Field)[N]) {
- return StringRef(Field, N).rtrim(" ");
-}
-
-template <class T>
-StringRef CommonArchiveMemberHeader<T>::getRawAccessMode() const {
- return getFieldRawString(ArMemHdr->AccessMode);
-}
-
-template <class T>
-StringRef CommonArchiveMemberHeader<T>::getRawLastModified() const {
- return getFieldRawString(ArMemHdr->LastModified);
-}
-
-template <class T> StringRef CommonArchiveMemberHeader<T>::getRawUID() const {
- return getFieldRawString(ArMemHdr->UID);
-}
-
-template <class T> StringRef CommonArchiveMemberHeader<T>::getRawGID() const {
- return getFieldRawString(ArMemHdr->GID);
-}
-
-template <class T> uint64_t CommonArchiveMemberHeader<T>::getOffset() const {
- return reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
-}
-
ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent,
const char *RawHeaderPtr,
uint64_t Size, Error *Err)
- : CommonArchiveMemberHeader<UnixArMemHdrType>(
- Parent, reinterpret_cast<const UnixArMemHdrType *>(RawHeaderPtr)) {
+ : Parent(Parent),
+ ArMemHdr(reinterpret_cast<const ArMemHdrType *>(RawHeaderPtr)) {
if (RawHeaderPtr == nullptr)
return;
ErrorAsOutParameter ErrAsOutParam(Err);
- if (Size < getSizeOf()) {
- *Err = createMemberHeaderParseError(this, RawHeaderPtr, Size);
+ if (Size < sizeof(ArMemHdrType)) {
+ if (Err) {
+ std::string Msg("remaining size of archive too small for next archive "
+ "member header ");
+ Expected<StringRef> NameOrErr = getName(Size);
+ if (!NameOrErr) {
+ consumeError(NameOrErr.takeError());
+ uint64_t Offset = RawHeaderPtr - Parent->getData().data();
+ *Err = malformedError(Msg + "at offset " + Twine(Offset));
+ } else
+ *Err = malformedError(Msg + "for " + NameOrErr.get());
+ }
return;
}
if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') {
@@ -124,19 +94,6 @@ ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent,
}
}
-BigArchiveMemberHeader::BigArchiveMemberHeader(const Archive *Parent,
- const char *RawHeaderPtr,
- uint64_t Size, Error *Err)
- : CommonArchiveMemberHeader<BigArMemHdrType>(
- Parent, reinterpret_cast<const BigArMemHdrType *>(RawHeaderPtr)) {
- if (RawHeaderPtr == nullptr)
- return;
- ErrorAsOutParameter ErrAsOutParam(Err);
-
- if (Size < getSizeOf())
- *Err = createMemberHeaderParseError(this, RawHeaderPtr, Size);
-}
-
// This gets the raw name from the ArMemHdr->Name field and checks that it is
// valid for the kind of archive. If it is not valid it returns an Error.
Expected<StringRef> ArchiveMemberHeader::getRawName() const {
@@ -164,69 +121,7 @@ Expected<StringRef> ArchiveMemberHeader::getRawName() const {
return StringRef(ArMemHdr->Name, end);
}
-Expected<uint64_t>
-getArchiveMemberDecField(Twine FieldName, const StringRef RawField,
- const Archive *Parent,
- const AbstractArchiveMemberHeader *MemHeader) {
- uint64_t Value;
- if (RawField.getAsInteger(10, Value)) {
- uint64_t Offset = MemHeader->getOffset();
- return malformedError("characters in " + FieldName +
- " field in archive member header are not "
- "all decimal numbers: '" +
- RawField +
- "' for the archive "
- "member header at offset " +
- Twine(Offset));
- }
- return Value;
-}
-
-Expected<uint64_t>
-getArchiveMemberOctField(Twine FieldName, const StringRef RawField,
- const Archive *Parent,
- const AbstractArchiveMemberHeader *MemHeader) {
- uint64_t Value;
- if (RawField.getAsInteger(8, Value)) {
- uint64_t Offset = MemHeader->getOffset();
- return malformedError("characters in " + FieldName +
- " field in archive member header are not "
- "all octal numbers: '" +
- RawField +
- "' for the archive "
- "member header at offset " +
- Twine(Offset));
- }
- return Value;
-}
-
-Expected<StringRef> BigArchiveMemberHeader::getRawName() const {
- Expected<uint64_t> NameLenOrErr = getArchiveMemberDecField(
- "NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);
- if (!NameLenOrErr)
- // TODO: Out-of-line.
- return NameLenOrErr.takeError();
- uint64_t NameLen = NameLenOrErr.get();
-
- // If the name length is odd, pad with '\0' to get an even length. After
- // padding, there is the name terminator "`\n".
- uint64_t NameLenWithPadding = alignTo(NameLen, 2);
- StringRef NameTerminator = "`\n";
- StringRef NameStringWithNameTerminator =
- StringRef(ArMemHdr->Name, NameLenWithPadding + NameTerminator.size());
- if (!NameStringWithNameTerminator.endswith(NameTerminator)) {
- uint64_t Offset =
- reinterpret_cast<const char *>(ArMemHdr->Name + NameLenWithPadding) -
- Parent->getData().data();
- // TODO: Out-of-line.
- return malformedError(
- "name does not have name terminator \"`\\n\" for archive member"
- "header at offset " +
- Twine(Offset));
- }
- return StringRef(ArMemHdr->Name, NameLen);
-}
-
+// This gets the name looking up long names. Size is the size of the archive
// member including the header, so the size of any name following the header
// is checked to make sure it does not overflow.
Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
@@ -234,7 +129,7 @@ Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
// This can be called from the ArchiveMemberHeader constructor when the
// archive header is truncated to produce an error message with the name.
// Make sure the name field is not truncated.
- if (Size < offsetof(UnixArMemHdrType, Name) + sizeof(ArMemHdr->Name)) {
+ if (Size < offsetof(ArMemHdrType, Name) + sizeof(ArMemHdr->Name)) {
uint64_t ArchiveOffset =
reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
return malformedError("archive header truncated before the name field "
@@ -329,133 +224,126 @@ Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
return Name.drop_back(1);
}
-Expected<StringRef> BigArchiveMemberHeader::getName(uint64_t Size) const {
- return getRawName();
-}
-
Expected<uint64_t> ArchiveMemberHeader::getSize() const {
- return getArchiveMemberDecField("size", getFieldRawString(ArMemHdr->Size),
- Parent, this);
-}
-
-Expected<uint64_t> BigArchiveMemberHeader::getSize() const {
- Expected<uint64_t> SizeOrErr = getArchiveMemberDecField(
- "size", getFieldRawString(ArMemHdr->Size), Parent, this);
- if (!SizeOrErr)
- return SizeOrErr.takeError();
-
- Expected<uint64_t> NameLenOrErr = getRawNameSize();
- if (!NameLenOrErr)
- return NameLenOrErr.takeError();
-
- return *SizeOrErr + alignTo(*NameLenOrErr, 2);
-}
-
-Expected<uint64_t> BigArchiveMemberHeader::getRawNameSize() const {
- return getArchiveMemberDecField(
- "NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);
-}
-
-Expected<uint64_t> BigArchiveMemberHeader::getNextOffset() const {
- return getArchiveMemberDecField(
- "NextOffset", getFieldRawString(ArMemHdr->NextOffset), Parent, this);
+ uint64_t Ret;
+ if (StringRef(ArMemHdr->Size, sizeof(ArMemHdr->Size))
+ .rtrim(" ")
+ .getAsInteger(10, Ret)) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ OS.write_escaped(
+ StringRef(ArMemHdr->Size, sizeof(ArMemHdr->Size)).rtrim(" "));
+ OS.flush();
+ uint64_t Offset =
+ reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
+ return malformedError("characters in size field in archive header are not "
+ "all decimal numbers: '" +
+ Buf +
+ "' for archive "
+ "member header at offset " +
+ Twine(Offset));
+ }
+ return Ret;
}
-Expected<sys::fs::perms> AbstractArchiveMemberHeader::getAccessMode() const {
- Expected<uint64_t> AccessModeOrErr =
- getArchiveMemberOctField("AccessMode", getRawAccessMode(), Parent, this);
- if (!AccessModeOrErr)
- return AccessModeOrErr.takeError();
- return static_cast<sys::fs::perms>(*AccessModeOrErr);
+Expected<sys::fs::perms> ArchiveMemberHeader::getAccessMode() const {
+ unsigned Ret;
+ if (StringRef(ArMemHdr->AccessMode, sizeof(ArMemHdr->AccessMode))
+ .rtrim(' ')
+ .getAsInteger(8, Ret)) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ OS.write_escaped(
+ StringRef(ArMemHdr->AccessMode, sizeof(ArMemHdr->AccessMode))
+ .rtrim(" "));
+ OS.flush();
+ uint64_t Offset =
+ reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
+ return malformedError("characters in AccessMode field in archive header "
+ "are not all decimal numbers: '" +
+ Buf + "' for the archive member header at offset " +
+ Twine(Offset));
+ }
+ return static_cast<sys::fs::perms>(Ret);
}
Expected<sys::TimePoint<std::chrono::seconds>>
-AbstractArchiveMemberHeader::getLastModified() const {
- Expected<uint64_t> SecondsOrErr = getArchiveMemberDecField(
- "LastModified", getRawLastModified(), Parent, this);
-
- if (!SecondsOrErr)
- return SecondsOrErr.takeError();
+ArchiveMemberHeader::getLastModified() const {
+ unsigned Seconds;
+ if (StringRef(ArMemHdr->LastModified, sizeof(ArMemHdr->LastModified))
+ .rtrim(' ')
+ .getAsInteger(10, Seconds)) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ OS.write_escaped(
+ StringRef(ArMemHdr->LastModified, sizeof(ArMemHdr->LastModified))
+ .rtrim(" "));
+ OS.flush();
+ uint64_t Offset =
+ reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
+ return malformedError("characters in LastModified field in archive header "
+ "are not all decimal numbers: '" +
+ Buf + "' for the archive member header at offset " +
+ Twine(Offset));
+ }
- return sys::toTimePoint(*SecondsOrErr);
+ return sys::toTimePoint(Seconds);
}
-Expected<unsigned> AbstractArchiveMemberHeader::getUID() const {
- StringRef User = getRawUID();
+Expected<unsigned> ArchiveMemberHeader::getUID() const {
+ unsigned Ret;
+ StringRef User = StringRef(ArMemHdr->UID, sizeof(ArMemHdr->UID)).rtrim(' ');
if (User.empty())
return 0;
- return getArchiveMemberDecField("UID", User, Parent, this);
+ if (User.getAsInteger(10, Ret)) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ OS.write_escaped(User);
+ OS.flush();
+ uint64_t Offset =
+ reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
+ return malformedError("characters in UID field in archive header "
+ "are not all decimal numbers: '" +
+ Buf + "' for the archive member header at offset " +
+ Twine(Offset));
+ }
+ return Ret;
}
-Expected<unsigned> AbstractArchiveMemberHeader::getGID() const {
- StringRef Group = getRawGID();
+Expected<unsigned> ArchiveMemberHeader::getGID() const {
+ unsigned Ret;
+ StringRef Group = StringRef(ArMemHdr->GID, sizeof(ArMemHdr->GID)).rtrim(' ');
if (Group.empty())
return 0;
- return getArchiveMemberDecField("GID", Group, Parent, this);
-}
-
-Expected<bool> ArchiveMemberHeader::isThin() const {
- Expected<StringRef> NameOrErr = getRawName();
- if (!NameOrErr)
- return NameOrErr.takeError();
- StringRef Name = NameOrErr.get();
- return Parent->isThin() && Name != "/" && Name != "//" && Name != "/SYM64/";
-}
-
-Expected<const char *> ArchiveMemberHeader::getNextChildLoc() const {
- uint64_t Size = getSizeOf();
- Expected<bool> isThinOrErr = isThin();
- if (!isThinOrErr)
- return isThinOrErr.takeError();
-
- bool isThin = isThinOrErr.get();
- if (!isThin) {
- Expected<uint64_t> MemberSize = getSize();
- if (!MemberSize)
- return MemberSize.takeError();
-
- Size += MemberSize.get();
+ if (Group.getAsInteger(10, Ret)) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ OS.write_escaped(Group);
+ OS.flush();
+ uint64_t Offset =
+ reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
+ return malformedError("characters in GID field in archive header "
+ "are not all decimal numbers: '" +
+ Buf + "' for the archive member header at offset " +
+ Twine(Offset));
}
-
- // If Size is odd, add 1 to make it even.
- const char *NextLoc =
- reinterpret_cast<const char *>(ArMemHdr) + alignTo(Size, 2);
-
- if (NextLoc == Parent->getMemoryBufferRef().getBufferEnd())
- return nullptr;
-
- return NextLoc;
-}
-
-Expected<const char *> BigArchiveMemberHeader::getNextChildLoc() const {
- if (getOffset() ==
- static_cast<const BigArchive *>(Parent)->getLastChildOffset())
- return nullptr;
-
- Expected<uint64_t> NextOffsetOrErr = getNextOffset();
- if (!NextOffsetOrErr)
- return NextOffsetOrErr.takeError();
- return Parent->getData().data() + NextOffsetOrErr.get();
+ return Ret;
}
Archive::Child::Child(const Archive *Parent, StringRef Data,
uint16_t StartOfFile)
- : Parent(Parent), Data(Data), StartOfFile(StartOfFile) {
- Header = Parent->createArchiveMemberHeader(Data.data(), Data.size(), nullptr);
-}
+ : Parent(Parent), Header(Parent, Data.data(), Data.size(), nullptr),
+ Data(Data), StartOfFile(StartOfFile) {}
Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
- : Parent(Parent) {
- if (!Start) {
- Header = nullptr;
+ : Parent(Parent),
+ Header(Parent, Start,
+ Parent
+ ? Parent->getData().size() - (Start - Parent->getData().data())
+ : 0,
+ Err) {
+ if (!Start)
return;
- }
-
- Header = Parent->createArchiveMemberHeader(
- Start,
- Parent ? Parent->getData().size() - (Start - Parent->getData().data())
- : 0,
- Err);
// If we are pointed to real data, Start is not a nullptr, then there must be
// a non-null Err pointer available to report malformed data on. Only in
@@ -470,7 +358,7 @@ Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
if (*Err)
return;
- uint64_t Size = Header->getSizeOf();
+ uint64_t Size = Header.getSizeOf();
Data = StringRef(Start, Size);
Expected<bool> isThinOrErr = isThinMember();
if (!isThinOrErr) {
@@ -489,7 +377,7 @@ Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
}
// Setup StartOfFile and PaddingBytes.
- StartOfFile = Header->getSizeOf();
+ StartOfFile = Header.getSizeOf();
// Don't include attached name.
Expected<StringRef> NameOrErr = getRawName();
if (!NameOrErr) {
@@ -497,20 +385,17 @@ Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
return;
}
StringRef Name = NameOrErr.get();
-
- if (Parent->kind() == Archive::K_AIXBIG) {
- // The actual start of the file is after the name and any necessary
- // even-alignment padding.
- StartOfFile += ((Name.size() + 1) >> 1) << 1;
- } else if (Name.startswith("#1/")) {
+ if (Name.startswith("#1/")) {
uint64_t NameSize;
- StringRef RawNameSize = Name.substr(3).rtrim(' ');
- if (RawNameSize.getAsInteger(10, NameSize)) {
+ if (Name.substr(3).rtrim(' ').getAsInteger(10, NameSize)) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ OS.write_escaped(Name.substr(3).rtrim(' '));
+ OS.flush();
uint64_t Offset = Start - Parent->getData().data();
*Err = malformedError("long name length characters after the #1/ are "
"not all decimal numbers: '" +
- RawNameSize +
- "' for archive member header at offset " +
+ Buf + "' for archive member header at offset " +
Twine(Offset));
return;
}
@@ -520,15 +405,21 @@ Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
Expected<uint64_t> Archive::Child::getSize() const {
if (Parent->IsThin)
- return Header->getSize();
+ return Header.getSize();
return Data.size() - StartOfFile;
}
Expected<uint64_t> Archive::Child::getRawSize() const {
- return Header->getSize();
+ return Header.getSize();
}
-Expected<bool> Archive::Child::isThinMember() const { return Header->isThin(); }
+Expected<bool> Archive::Child::isThinMember() const {
+ Expected<StringRef> NameOrErr = Header.getRawName();
+ if (!NameOrErr)
+ return NameOrErr.takeError();
+ StringRef Name = NameOrErr.get();
+ return Parent->IsThin && Name != "/" && Name != "//" && Name != "/SYM64/";
+}
Expected<std::string> Archive::Child::getFullName() const {
Expected<bool> isThin = isThinMember();
@@ -571,14 +462,15 @@ Expected<StringRef> Archive::Child::getBuffer() const {
}
Expected<Archive::Child> Archive::Child::getNext() const {
- Expected<const char *> NextLocOrErr = Header->getNextChildLoc();
- if (!NextLocOrErr)
- return NextLocOrErr.takeError();
+ size_t SpaceToSkip = Data.size();
+ // If it's odd, add 1 to make it even.
+ if (SpaceToSkip & 1)
+ ++SpaceToSkip;
- const char *NextLoc = *NextLocOrErr;
+ const char *NextLoc = Data.data() + SpaceToSkip;
// Check to see if this is at the end of the archive.
- if (NextLoc == nullptr)
+ if (NextLoc == Parent->Data.getBufferEnd())
return Child(nullptr, nullptr, nullptr);
// Check to see if this is past the end of the archive.
@@ -613,8 +505,7 @@ Expected<StringRef> Archive::Child::getName() const {
if (!RawSizeOrErr)
return RawSizeOrErr.takeError();
uint64_t RawSize = RawSizeOrErr.get();
- Expected<StringRef> NameOrErr =
- Header->getName(Header->getSizeOf() + RawSize);
+ Expected<StringRef> NameOrErr = Header.getName(Header.getSizeOf() + RawSize);
if (!NameOrErr)
return NameOrErr.takeError();
StringRef Name = NameOrErr.get();
@@ -646,39 +537,12 @@ Archive::Child::getAsBinary(LLVMContext *Context) const {
Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {
Error Err = Error::success();
- std::unique_ptr<Archive> Ret;
- StringRef Buffer = Source.getBuffer();
-
- if (Buffer.startswith(BigArchiveMagic))
- Ret = std::make_unique<BigArchive>(Source, Err);
- else
- Ret = std::make_unique<Archive>(Source, Err);
-
+ std::unique_ptr<Archive> Ret(new Archive(Source, Err));
if (Err)
return std::move(Err);
return std::move(Ret);
}
-std::unique_ptr<AbstractArchiveMemberHeader>
-Archive::createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size,
- Error *Err) const {
- ErrorAsOutParameter ErrAsOutParam(Err);
- if (kind() != K_AIXBIG)
- return std::make_unique<ArchiveMemberHeader>(this, RawHeaderPtr, Size, Err);
- return std::make_unique<BigArchiveMemberHeader>(this, RawHeaderPtr, Size,
- Err);
-}
-
-uint64_t Archive::getArchiveMagicLen() const {
- if (isThin())
- return sizeof(ThinArchiveMagic) - 1;
-
- if (Kind() == K_AIXBIG)
- return sizeof(BigArchiveMagic) - 1;
-
- return sizeof(ArchiveMagic) - 1;
-}
-
void Archive::setFirstRegular(const Child &C) {
FirstRegularData = C.Data;
FirstRegularStartOfFile = C.StartOfFile;
@@ -689,14 +553,10 @@ Archive::Archive(MemoryBufferRef Source, Error &Err)
ErrorAsOutParameter ErrAsOutParam(&Err);
StringRef Buffer = Data.getBuffer();
// Check for sufficient magic.
- if (Buffer.startswith(ThinArchiveMagic)) {
+ if (Buffer.startswith(ThinMagic)) {
IsThin = true;
- } else if (Buffer.startswith(ArchiveMagic)) {
- IsThin = false;
- } else if (Buffer.startswith(BigArchiveMagic)) {
- Format = K_AIXBIG;
+ } else if (Buffer.startswith(Magic)) {
IsThin = false;
- return;
} else {
Err = make_error<GenericBinaryError>("file too small to be an archive",
object_error::invalid_file_type);
@@ -928,7 +788,7 @@ Archive::child_iterator Archive::child_begin(Error &Err,
return child_iterator::itr(
Child(this, FirstRegularData, FirstRegularStartOfFile), Err);
- const char *Loc = Data.getBufferStart() + getFirstChildOffset();
+ const char *Loc = Data.getBufferStart() + strlen(Magic);
Child C(this, Loc, &Err);
if (Err)
return child_end();
@@ -1137,39 +997,6 @@ Expected<Optional<Archive::Child>> Archive::findSym(StringRef name) const {
}
// Returns true if archive file contains no member file.
-bool Archive::isEmpty() const {
- return Data.getBufferSize() == getArchiveMagicLen();
-}
+bool Archive::isEmpty() const { return Data.getBufferSize() == 8; }
bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }
-
-BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)
- : Archive(Source, Err) {
- ErrorAsOutParameter ErrAsOutParam(&Err);
- StringRef Buffer = Data.getBuffer();
- ArFixLenHdr = reinterpret_cast<const FixLenHdr *>(Buffer.data());
-
- StringRef RawOffset = getFieldRawString(ArFixLenHdr->FirstChildOffset);
- if (RawOffset.getAsInteger(10, FirstChildOffset))
- // TODO: Out-of-line.
- Err = malformedError("malformed AIX big archive: first member offset \"" +
- RawOffset + "\" is not a number");
-
- RawOffset = getFieldRawString(ArFixLenHdr->LastChildOffset);
- if (RawOffset.getAsInteger(10, LastChildOffset))
- // TODO: Out-of-line.
- Err = malformedError("malformed AIX big archive: last member offset \"" +
- RawOffset + "\" is not a number");
-
- child_iterator I = child_begin(Err, false);
- if (Err)
- return;
- child_iterator E = child_end();
- if (I == E) {
- Err = Error::success();
- return;
- }
- setFirstRegular(*I);
- Err = Error::success();
- return;
-}