diff options
author | Florian Hahn <flo@fhahn.com> | 2022-01-18 12:41:45 +0000 |
---|---|---|
committer | Florian Hahn <flo@fhahn.com> | 2022-01-18 12:44:16 +0000 |
commit | 1b9d323a266c9cc125e1993be56db97d71f25d39 (patch) | |
tree | a2ba481b63b9673293c9923662457453f68aee4e /llvm/lib/Object/Archive.cpp | |
parent | e781620dee4415018bdf3769a97c2ec31a85ff68 (diff) | |
download | llvm-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.cpp | 465 |
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; -} |