[AIX] support read global symbol of big archive

Reviewers: James Henderson, Fangrui Song

Differential Revision: https://reviews.llvm.org/D124865
This commit is contained in:
zhijian 2022-07-18 10:43:30 -04:00
parent 8aad330eeb
commit a6316d6da5
5 changed files with 96 additions and 5 deletions

View File

@ -379,10 +379,10 @@ protected:
uint64_t getArchiveMagicLen() const;
void setFirstRegular(const Child &C);
private:
StringRef SymbolTable;
StringRef StringTable;
private:
StringRef FirstRegularData;
uint16_t FirstRegularStartOfFile = -1;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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