Skip to content

Commit a6316d6

Browse files
committed
[AIX] support read global symbol of big archive
Reviewers: James Henderson, Fangrui Song Differential Revision: https://reviews.llvm.org/D124865
1 parent 8aad330 commit a6316d6

File tree

5 files changed

+96
-5
lines changed

5 files changed

+96
-5
lines changed

llvm/include/llvm/Object/Archive.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,10 @@ class Archive : public Binary {
379379
uint64_t getArchiveMagicLen() const;
380380
void setFirstRegular(const Child &C);
381381

382-
private:
383382
StringRef SymbolTable;
384383
StringRef StringTable;
385384

385+
private:
386386
StringRef FirstRegularData;
387387
uint16_t FirstRegularStartOfFile = -1;
388388

llvm/lib/Object/Archive.cpp

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -965,14 +965,15 @@ StringRef Archive::Symbol::getName() const {
965965
Expected<Archive::Child> Archive::Symbol::getMember() const {
966966
const char *Buf = Parent->getSymbolTable().begin();
967967
const char *Offsets = Buf;
968-
if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64)
968+
if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64 ||
969+
Parent->kind() == K_AIXBIG)
969970
Offsets += sizeof(uint64_t);
970971
else
971972
Offsets += sizeof(uint32_t);
972973
uint64_t Offset = 0;
973974
if (Parent->kind() == K_GNU) {
974975
Offset = read32be(Offsets + SymbolIndex * 4);
975-
} else if (Parent->kind() == K_GNU64) {
976+
} else if (Parent->kind() == K_GNU64 || Parent->kind() == K_AIXBIG) {
976977
Offset = read64be(Offsets + SymbolIndex * 8);
977978
} else if (Parent->kind() == K_BSD) {
978979
// The SymbolIndex is an index into the ranlib structs that start at
@@ -1105,6 +1106,8 @@ Archive::symbol_iterator Archive::symbol_begin() const {
11051106
// Skip the byte count of the string table.
11061107
buf += sizeof(uint64_t);
11071108
buf += ran_strx;
1109+
} else if (kind() == K_AIXBIG) {
1110+
buf = getStringTable().begin();
11081111
} else {
11091112
uint32_t member_count = 0;
11101113
uint32_t symbol_count = 0;
@@ -1127,7 +1130,7 @@ uint32_t Archive::getNumberOfSymbols() const {
11271130
const char *buf = getSymbolTable().begin();
11281131
if (kind() == K_GNU)
11291132
return read32be(buf);
1130-
if (kind() == K_GNU64)
1133+
if (kind() == K_GNU64 || kind() == K_AIXBIG)
11311134
return read64be(buf);
11321135
if (kind() == K_BSD)
11331136
return read32le(buf) / 8;
@@ -1180,6 +1183,58 @@ BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)
11801183
Err = malformedError("malformed AIX big archive: last member offset \"" +
11811184
RawOffset + "\" is not a number");
11821185

1186+
// Calculate the global symbol table.
1187+
uint64_t GlobSymOffset = 0;
1188+
RawOffset = getFieldRawString(ArFixLenHdr->GlobSymOffset);
1189+
if (RawOffset.getAsInteger(10, GlobSymOffset))
1190+
// TODO: add test case.
1191+
Err = malformedError(
1192+
"malformed AIX big archive: global symbol table offset \"" + RawOffset +
1193+
"\" is not a number");
1194+
1195+
if (Err)
1196+
return;
1197+
1198+
if (GlobSymOffset > 0) {
1199+
uint64_t BufferSize = Data.getBufferSize();
1200+
uint64_t GlobalSymTblContentOffset =
1201+
GlobSymOffset + sizeof(BigArMemHdrType);
1202+
if (GlobalSymTblContentOffset > BufferSize) {
1203+
Err = malformedError("global symbol table header at offset 0x" +
1204+
Twine::utohexstr(GlobSymOffset) + " and size 0x" +
1205+
Twine::utohexstr(sizeof(BigArMemHdrType)) +
1206+
" goes past the end of file");
1207+
return;
1208+
}
1209+
1210+
const char *GlobSymTblLoc = Data.getBufferStart() + GlobSymOffset;
1211+
const BigArMemHdrType *GlobalSymHdr =
1212+
reinterpret_cast<const BigArMemHdrType *>(GlobSymTblLoc);
1213+
RawOffset = getFieldRawString(GlobalSymHdr->Size);
1214+
uint64_t Size;
1215+
if (RawOffset.getAsInteger(10, Size)) {
1216+
// TODO: add test case.
1217+
Err = malformedError(
1218+
"malformed AIX big archive: global symbol table size \"" + RawOffset +
1219+
"\" is not a number");
1220+
return;
1221+
}
1222+
if (GlobalSymTblContentOffset + Size > BufferSize) {
1223+
Err = malformedError("global symbol table content at offset 0x" +
1224+
Twine::utohexstr(GlobalSymTblContentOffset) +
1225+
" and size 0x" + Twine::utohexstr(Size) +
1226+
" goes past the end of file");
1227+
return;
1228+
}
1229+
SymbolTable = StringRef(GlobSymTblLoc + sizeof(BigArMemHdrType), Size);
1230+
unsigned SymNum = getNumberOfSymbols();
1231+
unsigned SymOffsetsSize = 8 * (SymNum + 1);
1232+
uint64_t SymbolTableStringSize = Size - SymOffsetsSize;
1233+
StringTable =
1234+
StringRef(GlobSymTblLoc + sizeof(BigArMemHdrType) + SymOffsetsSize,
1235+
SymbolTableStringSize);
1236+
}
1237+
11831238
child_iterator I = child_begin(Err, false);
11841239
if (Err)
11851240
return;

llvm/test/Object/archive-symtab.test

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ Symbols:
6565
# RUN: llvm-nm --print-armap %t.a | FileCheck %s
6666
# RUN: not grep '/SYM64/' %t.a
6767

68+
# RUN: rm -f %t.a
69+
# RUN: llvm-ar rcsU --format=bigarchive %t.a %t.elf-x86-64 %t2.elf-x86-64
70+
# RUN: llvm-nm --print-armap %t.a | FileCheck %s
71+
6872
# CHECK: Archive map
6973
# CHECK-NEXT: main in {{.*}}.elf-x86-64
7074
# CHECK-NEXT: foo in {{.*}}2.elf-x86-64

llvm/test/tools/llvm-ar/delete.test

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# XFAIL: system-aix
21
## Test the deletion of members and that symbols are removed from the symbol table.
32

43
# RUN: yaml2obj %s -o %t-delete.o --docnum=1
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
## Test malformed global symbal table of big archive.
2+
3+
# RUN: rm -rf %t && mkdir %t && cd %t
4+
# RUN: yaml2obj %s -o t.o
5+
# RUN: llvm-ar q t.a t.o
6+
# RUN: cp t.a t2.a
7+
8+
## Truncate the file to end before the global symbol table header ends.
9+
# RUN: %python -c "with open('t.a', 'r+b') as input: input.truncate(560)"
10+
## Truncate the file to end before the global symbol table ends.
11+
# RUN: %python -c "with open('t2.a', 'r+b') as input: input.truncate(656)"
12+
13+
# RUN: not llvm-ar t t.a 2>&1 | FileCheck -DFILE=t.a %s
14+
# RUN: not llvm-ar t t2.a 2>&1 | FileCheck -DFILE=t2.a --check-prefixes=CHECK2 %s
15+
16+
# 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)
17+
# 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)
18+
19+
--- !XCOFF
20+
FileHeader:
21+
MagicNumber: 0x1DF
22+
Sections:
23+
- Name: .data
24+
Flags: [ STYP_DATA ]
25+
Symbols:
26+
- Name: export_protected_var
27+
Section: .data
28+
Type: 0x4000
29+
StorageClass: C_EXT
30+
AuxEntries:
31+
- Type: AUX_CSECT
32+
SymbolAlignmentAndType: 0x09
33+
StorageMappingClass: XMC_RW

0 commit comments

Comments
 (0)