[llvm] a6316d6 - [AIX] support read global symbol of big archive

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 18 07:44:05 PDT 2022


Author: zhijian
Date: 2022-07-18T10:43:30-04:00
New Revision: a6316d6da5938328840d4161e4dc7c671808c20f

URL: https://github.com/llvm/llvm-project/commit/a6316d6da5938328840d4161e4dc7c671808c20f
DIFF: https://github.com/llvm/llvm-project/commit/a6316d6da5938328840d4161e4dc7c671808c20f.diff

LOG: [AIX] support read global symbol of big archive

Reviewers: James Henderson, Fangrui Song

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

Added: 
    llvm/test/tools/llvm-ar/malformed-global-symbol-table-bigarchive.test

Modified: 
    llvm/include/llvm/Object/Archive.h
    llvm/lib/Object/Archive.cpp
    llvm/test/Object/archive-symtab.test
    llvm/test/tools/llvm-ar/delete.test

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h
index a36c9bd6163b..63f0df85054e 100644
--- a/llvm/include/llvm/Object/Archive.h
+++ b/llvm/include/llvm/Object/Archive.h
@@ -379,10 +379,10 @@ class Archive : public Binary {
   uint64_t getArchiveMagicLen() const;
   void setFirstRegular(const Child &C);
 
-private:
   StringRef SymbolTable;
   StringRef StringTable;
 
+private:
   StringRef FirstRegularData;
   uint16_t FirstRegularStartOfFile = -1;
 

diff  --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
index ad03f9cae9f8..1dffe007b9a9 100644
--- a/llvm/lib/Object/Archive.cpp
+++ b/llvm/lib/Object/Archive.cpp
@@ -965,14 +965,15 @@ StringRef Archive::Symbol::getName() const {
 Expected<Archive::Child> Archive::Symbol::getMember() const {
   const char *Buf = Parent->getSymbolTable().begin();
   const char *Offsets = Buf;
-  if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64)
+  if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64 ||
+      Parent->kind() == K_AIXBIG)
     Offsets += sizeof(uint64_t);
   else
     Offsets += sizeof(uint32_t);
   uint64_t Offset = 0;
   if (Parent->kind() == K_GNU) {
     Offset = read32be(Offsets + SymbolIndex * 4);
-  } else if (Parent->kind() == K_GNU64) {
+  } else if (Parent->kind() == K_GNU64 || Parent->kind() == K_AIXBIG) {
     Offset = read64be(Offsets + SymbolIndex * 8);
   } else if (Parent->kind() == K_BSD) {
     // The SymbolIndex is an index into the ranlib structs that start at
@@ -1105,6 +1106,8 @@ Archive::symbol_iterator Archive::symbol_begin() const {
     // Skip the byte count of the string table.
     buf += sizeof(uint64_t);
     buf += ran_strx;
+  } else if (kind() == K_AIXBIG) {
+    buf = getStringTable().begin();
   } else {
     uint32_t member_count = 0;
     uint32_t symbol_count = 0;
@@ -1127,7 +1130,7 @@ uint32_t Archive::getNumberOfSymbols() const {
   const char *buf = getSymbolTable().begin();
   if (kind() == K_GNU)
     return read32be(buf);
-  if (kind() == K_GNU64)
+  if (kind() == K_GNU64 || kind() == K_AIXBIG)
     return read64be(buf);
   if (kind() == K_BSD)
     return read32le(buf) / 8;
@@ -1180,6 +1183,58 @@ BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)
     Err = malformedError("malformed AIX big archive: last member offset \"" +
                          RawOffset + "\" is not a number");
 
+  // Calculate the global symbol table.
+  uint64_t GlobSymOffset = 0;
+  RawOffset = getFieldRawString(ArFixLenHdr->GlobSymOffset);
+  if (RawOffset.getAsInteger(10, GlobSymOffset))
+    // TODO: add test case.
+    Err = malformedError(
+        "malformed AIX big archive: global symbol table offset \"" + RawOffset +
+        "\" is not a number");
+
+  if (Err)
+    return;
+
+  if (GlobSymOffset > 0) {
+    uint64_t BufferSize = Data.getBufferSize();
+    uint64_t GlobalSymTblContentOffset =
+        GlobSymOffset + sizeof(BigArMemHdrType);
+    if (GlobalSymTblContentOffset > BufferSize) {
+      Err = malformedError("global symbol table header at offset 0x" +
+                           Twine::utohexstr(GlobSymOffset) + " and size 0x" +
+                           Twine::utohexstr(sizeof(BigArMemHdrType)) +
+                           " goes past the end of file");
+      return;
+    }
+
+    const char *GlobSymTblLoc = Data.getBufferStart() + GlobSymOffset;
+    const BigArMemHdrType *GlobalSymHdr =
+        reinterpret_cast<const BigArMemHdrType *>(GlobSymTblLoc);
+    RawOffset = getFieldRawString(GlobalSymHdr->Size);
+    uint64_t Size;
+    if (RawOffset.getAsInteger(10, Size)) {
+      // TODO: add test case.
+      Err = malformedError(
+          "malformed AIX big archive: global symbol table size \"" + RawOffset +
+          "\" is not a number");
+      return;
+    }
+    if (GlobalSymTblContentOffset + Size > BufferSize) {
+      Err = malformedError("global symbol table content at offset 0x" +
+                           Twine::utohexstr(GlobalSymTblContentOffset) +
+                           " and size 0x" + Twine::utohexstr(Size) +
+                           " goes past the end of file");
+      return;
+    }
+    SymbolTable = StringRef(GlobSymTblLoc + sizeof(BigArMemHdrType), Size);
+    unsigned SymNum = getNumberOfSymbols();
+    unsigned SymOffsetsSize = 8 * (SymNum + 1);
+    uint64_t SymbolTableStringSize = Size - SymOffsetsSize;
+    StringTable =
+        StringRef(GlobSymTblLoc + sizeof(BigArMemHdrType) + SymOffsetsSize,
+                  SymbolTableStringSize);
+  }
+
   child_iterator I = child_begin(Err, false);
   if (Err)
     return;

diff  --git a/llvm/test/Object/archive-symtab.test b/llvm/test/Object/archive-symtab.test
index 9ef2ba29820d..69f1d226b2c1 100644
--- a/llvm/test/Object/archive-symtab.test
+++ b/llvm/test/Object/archive-symtab.test
@@ -65,6 +65,10 @@ Symbols:
 # RUN: llvm-nm --print-armap %t.a | FileCheck %s
 # RUN: not grep '/SYM64/' %t.a
 
+# RUN: rm -f %t.a
+# RUN: llvm-ar rcsU --format=bigarchive %t.a %t.elf-x86-64 %t2.elf-x86-64
+# RUN: llvm-nm --print-armap %t.a | FileCheck %s
+
 # CHECK: Archive map
 # CHECK-NEXT: main in {{.*}}.elf-x86-64
 # CHECK-NEXT: foo in {{.*}}2.elf-x86-64

diff  --git a/llvm/test/tools/llvm-ar/delete.test b/llvm/test/tools/llvm-ar/delete.test
index 6bf4481873ba..20e58b9a45b5 100644
--- a/llvm/test/tools/llvm-ar/delete.test
+++ b/llvm/test/tools/llvm-ar/delete.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## Test the deletion of members and that symbols are removed from the symbol table.
 
 # RUN: yaml2obj %s -o %t-delete.o --docnum=1

diff  --git a/llvm/test/tools/llvm-ar/malformed-global-symbol-table-bigarchive.test b/llvm/test/tools/llvm-ar/malformed-global-symbol-table-bigarchive.test
new file mode 100644
index 000000000000..d4a8f377d4d9
--- /dev/null
+++ b/llvm/test/tools/llvm-ar/malformed-global-symbol-table-bigarchive.test
@@ -0,0 +1,33 @@
+## Test malformed global symbal table of big archive.
+
+# RUN: rm -rf %t && mkdir %t && cd %t
+# RUN: yaml2obj %s -o t.o
+# RUN: llvm-ar q t.a t.o
+# RUN: cp t.a t2.a
+
+## Truncate the file to end before the global symbol table header ends.
+# RUN: %python -c "with open('t.a', 'r+b') as input: input.truncate(560)"
+## Truncate the file to end before the global symbol table ends.
+# RUN: %python -c "with open('t2.a', 'r+b') as input: input.truncate(656)"
+
+# RUN: not llvm-ar t t.a 2>&1 | FileCheck -DFILE=t.a %s
+# RUN: not llvm-ar t t2.a 2>&1 | FileCheck -DFILE=t2.a --check-prefixes=CHECK2 %s
+
+# CHECK:  error: unable to load '[[FILE]]': truncated or malformed archive (global symbol table header at offset 0x20e and size 0x72 goes past the end of file)
+# CHECK2: error: unable to load '[[FILE]]': truncated or malformed archive (global symbol table content at offset 0x280 and size 0x25 goes past the end of file)
+
+--- !XCOFF
+FileHeader:
+  MagicNumber:       0x1DF
+Sections:
+  - Name:            .data
+    Flags:           [ STYP_DATA ]
+Symbols:
+  - Name:            export_protected_var
+    Section:         .data
+    Type:            0x4000
+    StorageClass:    C_EXT
+    AuxEntries:
+     - Type:                   AUX_CSECT
+       SymbolAlignmentAndType: 0x09
+       StorageMappingClass:    XMC_RW


        


More information about the llvm-commits mailing list