]> granicus.if.org Git - llvm/commitdiff
[Object] Deduplicate long archive member names
authorPeter Wu <peter@lekensteyn.nl>
Wed, 19 Dec 2018 16:15:05 +0000 (16:15 +0000)
committerPeter Wu <peter@lekensteyn.nl>
Wed, 19 Dec 2018 16:15:05 +0000 (16:15 +0000)
Summary:
Import libraries as created by llvm-dlltool always use the same archive
member name for every object file (namely, the DLL library name). Ensure
that long names are not repeatedly stored in the string table.

Reviewed By: ruiu

Differential Revision: https://reviews.llvm.org/D55860

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349637 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Object/ArchiveWriter.cpp
test/Object/archive-format.test

index 767205390e0782bf655af0882c1751126b364461..4de5871c7ec0b655de0ea26daa1a43a10db4632b 100644 (file)
@@ -250,6 +250,7 @@ static void addToStringTable(raw_ostream &Out, StringRef ArcName,
 
 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,
@@ -262,8 +263,20 @@ static void printMemberHeader(raw_ostream &Out, uint64_t Pos,
     return printGNUSmallMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
                                      M.Perms, Size);
   Out << '/';
-  uint64_t NamePos = StringTable.tell();
-  addToStringTable(StringTable, ArcName, M, Thin);
+  uint64_t NamePos;
+  if (Thin) {
+    NamePos = StringTable.tell();
+    addToStringTable(StringTable, ArcName, M, Thin);
+  } else {
+    StringMap<uint64_t>::const_iterator it = MemberNames.find(M.MemberName);
+    if (it == MemberNames.end()) {
+      NamePos = StringTable.tell();
+      addToStringTable(StringTable, ArcName, M, Thin);
+      MemberNames[M.MemberName] = NamePos;
+    } else {
+      NamePos = it->second;
+    }
+  }
   printWithSpacePadding(Out, NamePos, 15);
   printRestOfMemberHeader(Out, ModTime, M.UID, M.GID, M.Perms, Size);
 }
@@ -433,6 +446,11 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
   std::vector<MemberData> Ret;
   bool HasObject = false;
 
+  // Deduplicate long member names in the string table and reuse earlier name
+  // offsets. This especially saves space for COFF Import libraries where all
+  // members have the same name.
+  StringMap<uint64_t> MemberNames;
+
   // UniqueTimestamps is a special case to improve debugging on Darwin:
   //
   // The Darwin linker does not link debug info into the final
@@ -505,8 +523,8 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
       ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);
     else
       ModTime = M.ModTime;
-    printMemberHeader(Out, Pos, StringTable, Kind, Thin, ArcName, M, ModTime,
-                      Buf.getBufferSize() + MemberPadding);
+    printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, ArcName,
+                      M, ModTime, Buf.getBufferSize() + MemberPadding);
     Out.flush();
 
     Expected<std::vector<unsigned>> Symbols =
index b1ae411161bc1bdc346f9e69c6d7c114d8bcaf39..b555bf88faca9164a5fcfafbec108a4f1e844388 100644 (file)
@@ -15,8 +15,7 @@ RUN: llvm-ar --format=gnu rc %t.a 0123456789abcde 0123456789abcdef foo/012345678
 RUN: cat %t.a | FileCheck -strict-whitespace %s
 
 CHECK:      !<arch>
-CHECK-NEXT: //                                              36        `
-CHECK-NEXT: 0123456789abcdef/
+CHECK-NEXT: //                                              18        `
 CHECK-NEXT: 0123456789abcdef/
 CHECK-NEXT: 0123456789abcde/0           0     0     644     4         `
 CHECK-NEXT: bar.
@@ -24,7 +23,7 @@ CHECK-SAME: /0              0           0     0     644     4         `
 CHECK-NEXT: zed.
 CHECK-SAME: 0123456789abcde/0           0     0     644     4         `
 CHECK-NEXT: bar2
-CHECK-SAME: /18             0           0     0     644     4         `
+CHECK-SAME: /             0           0     0     644     4         `
 CHECK-NEXT: zed2
 
 RUN: rm -f %t.a