diff options
author | Jordan Rupprecht <rupprecht@google.com> | 2019-02-13 23:39:41 +0000 |
---|---|---|
committer | Jordan Rupprecht <rupprecht@google.com> | 2019-02-13 23:39:41 +0000 |
commit | 451c2ef199e9c5163007ac32e2d426fbfb37e664 (patch) | |
tree | cd57778f72c88b3361134816f3b72645907ceaa1 /llvm/lib/Object/ArchiveWriter.cpp | |
parent | 1113940df2f81d60848d6e955d353b53397c84aa (diff) | |
download | bcm5719-llvm-451c2ef199e9c5163007ac32e2d426fbfb37e664.tar.gz bcm5719-llvm-451c2ef199e9c5163007ac32e2d426fbfb37e664.zip |
[llvm-ar][libObject] Fix relative paths when nesting thin archives.
Summary:
When adding one thin archive to another, we currently chop off the relative path to the flattened members. For instance, when adding `foo/child.a` (which contains `x.txt`) to `parent.a`, when flattening it we should add it as `foo/x.txt` (which exists) instead of `x.txt` (which does not exist).
As a note, this also undoes the `IsNew` parameter of handling relative paths in r288280. The unit test there still passes.
This was reported as part of testing the kernel build with llvm-ar: https://patchwork.kernel.org/patch/10767545/ (see the second point).
Reviewers: mstorsjo, pcc, ruiu, davide, david2050, inglorion
Reviewed By: ruiu
Subscribers: void, jdoerfert, tpimh, mgorny, hans, nickdesaulniers, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57842
llvm-svn: 353995
Diffstat (limited to 'llvm/lib/Object/ArchiveWriter.cpp')
-rw-r--r-- | llvm/lib/Object/ArchiveWriter.cpp | 112 |
1 files changed, 48 insertions, 64 deletions
diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp index d27233ec2f4..4116ed4628e 100644 --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -48,7 +48,6 @@ NewArchiveMember::getOldMember(const object::Archive::Child &OldMember, return BufOrErr.takeError(); NewArchiveMember M; - assert(M.IsNew == false); M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false); M.MemberName = M.Buf->getBufferIdentifier(); if (!Deterministic) { @@ -98,7 +97,6 @@ Expected<NewArchiveMember> NewArchiveMember::getFile(StringRef FileName, return errorCodeToError(std::error_code(errno, std::generic_category())); NewArchiveMember M; - M.IsNew = true; M.Buf = std::move(*MemberBufferOrErr); M.MemberName = M.Buf->getBufferIdentifier(); if (!Deterministic) { @@ -191,35 +189,6 @@ static bool useStringTable(bool Thin, StringRef Name) { return Thin || Name.size() >= 16 || Name.contains('/'); } -// Compute the relative path from From to To. -static std::string computeRelativePath(StringRef From, StringRef To) { - if (sys::path::is_absolute(From) || sys::path::is_absolute(To)) - return To; - - StringRef DirFrom = sys::path::parent_path(From); - auto FromI = sys::path::begin(DirFrom); - auto ToI = sys::path::begin(To); - while (*FromI == *ToI) { - ++FromI; - ++ToI; - } - - SmallString<128> Relative; - for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI) - sys::path::append(Relative, ".."); - - for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI) - sys::path::append(Relative, *ToI); - -#ifdef _WIN32 - // Replace backslashes with slashes so that the path is portable between *nix - // and Windows. - std::replace(Relative.begin(), Relative.end(), '\\', '/'); -#endif - - return Relative.str(); -} - static bool is64BitKind(object::Archive::Kind Kind) { switch (Kind) { case object::Archive::K_GNU: @@ -234,27 +203,11 @@ static bool is64BitKind(object::Archive::Kind Kind) { llvm_unreachable("not supported for writting"); } -static void addToStringTable(raw_ostream &Out, StringRef ArcName, - const NewArchiveMember &M, bool Thin) { - StringRef ID = M.Buf->getBufferIdentifier(); - if (Thin) { - if (M.IsNew) - Out << computeRelativePath(ArcName, ID); - else - Out << ID; - } else - Out << M.MemberName; - Out << "/\n"; -} - -static void printMemberHeader(raw_ostream &Out, uint64_t Pos, - raw_ostream &StringTable, - StringMap<uint64_t> &MemberNames, - object::Archive::Kind Kind, bool Thin, - StringRef ArcName, const NewArchiveMember &M, - sys::TimePoint<std::chrono::seconds> ModTime, - unsigned Size) { - +static void +printMemberHeader(raw_ostream &Out, uint64_t Pos, raw_ostream &StringTable, + StringMap<uint64_t> &MemberNames, object::Archive::Kind Kind, + bool Thin, const NewArchiveMember &M, + sys::TimePoint<std::chrono::seconds> ModTime, unsigned Size) { if (isBSDLike(Kind)) return printBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID, M.Perms, Size); @@ -265,12 +218,12 @@ static void printMemberHeader(raw_ostream &Out, uint64_t Pos, uint64_t NamePos; if (Thin) { NamePos = StringTable.tell(); - addToStringTable(StringTable, ArcName, M, Thin); + StringTable << M.MemberName << "/\n"; } else { auto Insertion = MemberNames.insert({M.MemberName, uint64_t(0)}); if (Insertion.second) { Insertion.first->second = StringTable.tell(); - addToStringTable(StringTable, ArcName, M, Thin); + StringTable << M.MemberName << "/\n"; } NamePos = Insertion.first->second; } @@ -432,8 +385,8 @@ getSymbols(MemoryBufferRef Buf, raw_ostream &SymNames, bool &HasObject) { static Expected<std::vector<MemberData>> computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, - object::Archive::Kind Kind, bool Thin, StringRef ArcName, - bool Deterministic, ArrayRef<NewArchiveMember> NewMembers) { + object::Archive::Kind Kind, bool Thin, bool Deterministic, + ArrayRef<NewArchiveMember> NewMembers) { static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'}; // This ignores the symbol table, but we only need the value mod 8 and the @@ -520,8 +473,8 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++); else ModTime = M.ModTime; - printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, ArcName, - M, ModTime, Buf.getBufferSize() + MemberPadding); + printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M, + ModTime, Buf.getBufferSize() + MemberPadding); Out.flush(); Expected<std::vector<unsigned>> Symbols = @@ -540,11 +493,40 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, return Ret; } -Error llvm::writeArchive(StringRef ArcName, - ArrayRef<NewArchiveMember> NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, - bool Deterministic, bool Thin, - std::unique_ptr<MemoryBuffer> OldArchiveBuf) { +namespace llvm { +// Compute the relative path from From to To. +std::string computeArchiveRelativePath(StringRef From, StringRef To) { + if (sys::path::is_absolute(From) || sys::path::is_absolute(To)) + return To; + + StringRef DirFrom = sys::path::parent_path(From); + auto FromI = sys::path::begin(DirFrom); + auto ToI = sys::path::begin(To); + while (*FromI == *ToI) { + ++FromI; + ++ToI; + } + + SmallString<128> Relative; + for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI) + sys::path::append(Relative, ".."); + + for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI) + sys::path::append(Relative, *ToI); + +#ifdef _WIN32 + // Replace backslashes with slashes so that the path is portable between *nix + // and Windows. + std::replace(Relative.begin(), Relative.end(), '\\', '/'); +#endif + + return Relative.str(); +} + +Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, + bool WriteSymtab, object::Archive::Kind Kind, + bool Deterministic, bool Thin, + std::unique_ptr<MemoryBuffer> OldArchiveBuf) { assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode"); SmallString<0> SymNamesBuf; @@ -553,7 +535,7 @@ Error llvm::writeArchive(StringRef ArcName, raw_svector_ostream StringTable(StringTableBuf); Expected<std::vector<MemberData>> DataOrErr = computeMemberData( - StringTable, SymNames, Kind, Thin, ArcName, Deterministic, NewMembers); + StringTable, SymNames, Kind, Thin, Deterministic, NewMembers); if (Error E = DataOrErr.takeError()) return E; std::vector<MemberData> &Data = *DataOrErr; @@ -630,3 +612,5 @@ Error llvm::writeArchive(StringRef ArcName, return Temp->keep(ArcName); } + +} // namespace llvm |