]> granicus.if.org Git - llvm/commitdiff
[llvm-ar] Implement the O modifier: display member offsets inside the archive
authorFangrui Song <maskray@google.com>
Thu, 17 Oct 2019 11:34:29 +0000 (11:34 +0000)
committerFangrui Song <maskray@google.com>
Thu, 17 Oct 2019 11:34:29 +0000 (11:34 +0000)
Since GNU ar 2.31, the 't' operation prints member offsets beside file
names if the 'O' modifier is specified. 'O' is ignored for thin
archives.

Reviewed By: gbreynoo, ruiu

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

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

docs/CommandGuide/llvm-ar.rst
include/llvm/Object/Archive.h
test/Object/archive-thin-create.test
test/Object/archive-toc.test
tools/llvm-ar/llvm-ar.cpp

index 1073d96cb7e10cab5032e4843311e203dc59708c..a138dcf16832e0eda3e12e43ec26974e3d9e4861 100644 (file)
@@ -100,15 +100,15 @@ r[abu]
  *files* or insert them at the end of the archive if they do not exist. If no
  *files* are specified, the archive is not modified.
 
-t[v]
+t[vO]
 
  Print the table of contents. Without any modifiers, this operation just prints
  the names of the members to the standard output. With the *v* modifier,
  **llvm-ar** also prints out the file type (B=bitcode, S=symbol
  table, blank=regular file), the permission mode, the owner and group, the
- size, and the date. If any *files* are specified, the listing is only for
- those files. If no *files* are specified, the table of contents for the
- whole archive is printed.
+ size, and the date. With the :option:`O` modifier, display member offsets.
+ If any *files* are specified, the listing is only for those files. If no
*files* are specified, the table of contents for the whole archive is printed.
 
 x[oP]
 
@@ -145,6 +145,10 @@ section (above) to determine which modifiers are applicable to which operations.
  When extracting files, this option will cause **llvm-ar** to preserve the
  original modification times of the files it writes.
 
+[O]
+
+ Display member offsets inside the archive.
+
 [u]
 
  When replacing existing files in the archive, only replace those files that have
index 8b58eaeff418cb472278769fd34f52292da6f930..c3f36bdd9d1a56b984efa873c6b084d65a4aea99 100644 (file)
@@ -135,6 +135,7 @@ public:
 
     Expected<StringRef> getBuffer() const;
     uint64_t getChildOffset() const;
+    uint64_t getDataOffset() const { return getChildOffset() + StartOfFile; }
 
     Expected<MemoryBufferRef> getMemoryBufferRef() const;
 
index 55abe0002f95ff156e278ff0580e4485b026fd33..e705d0ee2b7554b44dac9946ef84822706d9107f 100644 (file)
@@ -9,6 +9,9 @@ RUN: llvm-ar qcT foo/libtest.a foo/test1.o
 RUN: llvm-ar qcT foo/libtest.a foo/test2.o
 RUN: llvm-ar t foo/libtest.a | FileCheck --match-full-lines %s
 
+O (displaying member offsets) is ignored for thin archives.
+RUN: llvm-ar tO foo/libtest.a | FileCheck --match-full-lines %s
+
 CHECK: foo/test1.o
 CHECK: foo/test1.o
 CHECK: foo/test2.o
index fcc7fe5312ad8294dab57dca21adb35a7d3f2909..29f0bacfc3db7d41f1170cc49435178ab1024337 100644 (file)
@@ -46,3 +46,17 @@ RUN: env TZ=GMT llvm-ar tv Inputs/thin-path.a | FileCheck %s --check-prefix=THIN
 
 THINPATH:      rw-r--r-- 0/0   1224 Jan  1 00:00 1970 Inputs/test.o
 THINPATH-NEXT: rw-r--r-- 0/0   1224 Jan  1 00:00 1970 Inputs/t/test2.o
+
+RUN: llvm-ar tO Inputs/GNU.a | FileCheck %s --check-prefix=GNU-O --strict-whitespace
+
+GNU-O:      {{^}}evenlen 0x10c
+GNU-O-NEXT: {{^}}oddlen 0x150
+GNU-O-NEXT: {{^}}very_long_bytecode_file_name.bc 0x194
+GNU-O-NEXT: {{^}}IsNAN.o 0x78a
+
+RUN: env TZ=GMT llvm-ar tvO Inputs/GNU.a | FileCheck %s --check-prefix=GNU-VO --strict-whitespace
+
+GNU-VO:      rw-r--r-- 500/500      8 Nov 19 02:57 2004 evenlen 0x10c
+GNU-VO-NEXT: rw-r--r-- 500/500      7 Nov 19 02:57 2004 oddlen 0x150
+GNU-VO-NEXT: rwxr-xr-x 500/500   1465 Nov 19 03:01 2004 very_long_bytecode_file_name.bc 0x194
+GNU-VO-NEXT: rw-r--r-- 500/500   2280 Nov 19 03:04 2004 IsNAN.o 0x78a
index 6233c60e9bdc60687000a7afdbf97f8e5c8cc3ad..c9cf217f7688d18fcfc47eea752ac481efc45f1b 100644 (file)
@@ -106,6 +106,7 @@ MODIFIERS:
   [L] - add archive's contents
   [N] - use instance [count] of name
   [o] - preserve original dates
+  [O] - display member offsets
   [P] - use full names when matching (implied for thin archives)
   [s] - create an archive index (cf. ranlib)
   [S] - do not build a symbol table
@@ -187,17 +188,18 @@ enum ArchiveOperation {
 };
 
 // Modifiers to follow operation to vary behavior
-static bool AddAfter = false;        ///< 'a' modifier
-static bool AddBefore = false;       ///< 'b' modifier
-static bool Create = false;          ///< 'c' modifier
-static bool OriginalDates = false;   ///< 'o' modifier
-static bool CompareFullPath = false; ///< 'P' modifier
-static bool OnlyUpdate = false;      ///< 'u' modifier
-static bool Verbose = false;         ///< 'v' modifier
-static bool Symtab = true;           ///< 's' modifier
-static bool Deterministic = true;    ///< 'D' and 'U' modifiers
-static bool Thin = false;            ///< 'T' modifier
-static bool AddLibrary = false;      ///< 'L' modifier
+static bool AddAfter = false;             ///< 'a' modifier
+static bool AddBefore = false;            ///< 'b' modifier
+static bool Create = false;               ///< 'c' modifier
+static bool OriginalDates = false;        ///< 'o' modifier
+static bool DisplayMemberOffsets = false; ///< 'O' modifier
+static bool CompareFullPath = false;      ///< 'P' modifier
+static bool OnlyUpdate = false;           ///< 'u' modifier
+static bool Verbose = false;              ///< 'v' modifier
+static bool Symtab = true;                ///< 's' modifier
+static bool Deterministic = true;         ///< 'D' and 'U' modifiers
+static bool Thin = false;                 ///< 'T' modifier
+static bool AddLibrary = false;           ///< 'L' modifier
 
 // Relative Positional Argument (for insert/move). This variable holds
 // the name of the archive member to which the 'a', 'b' or 'i' modifier
@@ -329,6 +331,9 @@ static ArchiveOperation parseCommandLine() {
     case 'o':
       OriginalDates = true;
       break;
+    case 'O':
+      DisplayMemberOffsets = true;
+      break;
     case 'P':
       CompareFullPath = true;
       break;
@@ -486,8 +491,13 @@ static void doDisplayTable(StringRef Name, const object::Archive::Child &C) {
       if (!ParentDir.empty())
         outs() << sys::path::convert_to_slash(ParentDir) << '/';
     }
+    outs() << Name;
+  } else {
+    outs() << Name;
+    if (DisplayMemberOffsets)
+      outs() << " 0x" << utohexstr(C.getDataOffset(), true);
   }
-  outs() << Name << "\n";
+  outs() << '\n';
 }
 
 static std::string normalizePath(StringRef Path) {