aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/Archive.cpp
diff options
context:
space:
mode:
authorzhijian <zhijian@ca.ibm.com>2022-07-18 10:43:30 -0400
committerzhijian <zhijian@ca.ibm.com>2022-07-18 10:43:30 -0400
commita6316d6da5938328840d4161e4dc7c671808c20f (patch)
tree443adfcf313bd9f07a54be6e668d2c661ac562e5 /llvm/lib/Object/Archive.cpp
parent8aad330eebc0b9cfd8dd00e8ed692cb89e7577df (diff)
downloadllvm-a6316d6da5938328840d4161e4dc7c671808c20f.zip
llvm-a6316d6da5938328840d4161e4dc7c671808c20f.tar.gz
llvm-a6316d6da5938328840d4161e4dc7c671808c20f.tar.bz2
[AIX] support read global symbol of big archive
Reviewers: James Henderson, Fangrui Song Differential Revision: https://reviews.llvm.org/D124865
Diffstat (limited to 'llvm/lib/Object/Archive.cpp')
-rw-r--r--llvm/lib/Object/Archive.cpp61
1 files changed, 58 insertions, 3 deletions
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
index ad03f9c..1dffe00 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;