Skip to content

[XCOFF][OBJECT] get symbol size by calling XCOFF interfaces #67304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 51 additions & 17 deletions llvm/include/llvm/Object/XCOFFObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Endian.h"
Expand All @@ -23,6 +24,8 @@
namespace llvm {
namespace object {

class xcoff_symbol_iterator;

struct XCOFFFileHeader32 {
support::ubig16_t Magic;
support::ubig16_t NumberOfSections;
Expand Down Expand Up @@ -576,6 +579,10 @@ class XCOFFObjectFile : public ObjectFile {
Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
basic_symbol_iterator symbol_begin() const override;
basic_symbol_iterator symbol_end() const override;

using xcoff_symbol_iterator_range = iterator_range<xcoff_symbol_iterator>;
xcoff_symbol_iterator_range symbols() const;

bool is64Bit() const override;
Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
Expand Down Expand Up @@ -761,33 +768,47 @@ struct XCOFFSymbolEntry64 {
uint8_t NumberOfAuxEntries;
};

class XCOFFSymbolRef {
class XCOFFSymbolRef : public SymbolRef {
public:
enum { NAME_IN_STR_TBL_MAGIC = 0x0 };

XCOFFSymbolRef(DataRefImpl SymEntDataRef,
const XCOFFObjectFile *OwningObjectPtr)
: OwningObjectPtr(OwningObjectPtr) {
: SymbolRef(SymEntDataRef, OwningObjectPtr) {
assert(OwningObjectPtr && "OwningObjectPtr cannot be nullptr!");
assert(SymEntDataRef.p != 0 &&
"Symbol table entry pointer cannot be nullptr!");
}

if (OwningObjectPtr->is64Bit())
Entry64 = reinterpret_cast<const XCOFFSymbolEntry64 *>(SymEntDataRef.p);
else
Entry32 = reinterpret_cast<const XCOFFSymbolEntry32 *>(SymEntDataRef.p);
const XCOFFSymbolEntry32 *getSymbol32() const {
return reinterpret_cast<const XCOFFSymbolEntry32 *>(getRawDataRefImpl().p);
}
const XCOFFSymbolEntry64 *getSymbol64() const {
return reinterpret_cast<const XCOFFSymbolEntry64 *>(getRawDataRefImpl().p);
}

const XCOFFSymbolEntry32 *getSymbol32() { return Entry32; }
const XCOFFSymbolEntry64 *getSymbol64() { return Entry64; }
uint64_t getValue() const {
return getObject()->is64Bit() ? getValue64() : getValue32();
}

uint64_t getValue() const { return Entry32 ? getValue32() : getValue64(); }
uint32_t getValue32() const {
return reinterpret_cast<const XCOFFSymbolEntry32 *>(getRawDataRefImpl().p)
->Value;
}

uint32_t getValue32() const { return Entry32->Value; }
uint64_t getValue64() const {
return reinterpret_cast<const XCOFFSymbolEntry64 *>(getRawDataRefImpl().p)
->Value;
}

uint64_t getValue64() const { return Entry64->Value; }
uint64_t getSize() const {
return getObject()->getSymbolSize(getRawDataRefImpl());
}

#define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
#define GETVALUE(X) \
getObject()->is64Bit() \
? reinterpret_cast<const XCOFFSymbolEntry64 *>(getRawDataRefImpl().p)->X \
: reinterpret_cast<const XCOFFSymbolEntry32 *>(getRawDataRefImpl().p)->X

int16_t getSectionNumber() const { return GETVALUE(SectionNumber); }

Expand All @@ -812,8 +833,7 @@ class XCOFFSymbolRef {
#undef GETVALUE

uintptr_t getEntryAddress() const {
return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
: reinterpret_cast<uintptr_t>(Entry64);
return getRawDataRefImpl().p;
}

Expected<StringRef> getName() const;
Expand All @@ -822,9 +842,23 @@ class XCOFFSymbolRef {
Expected<XCOFFCsectAuxRef> getXCOFFCsectAuxRef() const;

private:
const XCOFFObjectFile *OwningObjectPtr;
const XCOFFSymbolEntry32 *Entry32 = nullptr;
const XCOFFSymbolEntry64 *Entry64 = nullptr;
const XCOFFObjectFile *getObject() const {
return cast<XCOFFObjectFile>(BasicSymbolRef::getObject());
}
};

class xcoff_symbol_iterator : public symbol_iterator {
public:
xcoff_symbol_iterator(const basic_symbol_iterator &B)
: symbol_iterator(B) {}

const XCOFFSymbolRef *operator->() const {
return static_cast<const XCOFFSymbolRef *>(symbol_iterator::operator->());
}

const XCOFFSymbolRef &operator*() const {
return static_cast<const XCOFFSymbolRef &>(symbol_iterator::operator*());
}
};

class TBVectorExt {
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Object/SymbolSize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ llvm::object::computeSymbolSizes(const ObjectFile &O) {
return Ret;
}

if (const auto *E = dyn_cast<XCOFFObjectFile>(&O)) {
auto Syms = E->symbols();
for (XCOFFSymbolRef Sym : Syms)
Ret.push_back({Sym, Sym.getSize()});
return Ret;
}

// Collect sorted symbol addresses. Include dummy addresses for the end
// of each section.
std::vector<SymEntry> Addresses;
Expand Down
27 changes: 16 additions & 11 deletions llvm/lib/Object/XCOFFObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,10 @@ basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
return basic_symbol_iterator(SymbolRef(SymDRI, this));
}

XCOFFObjectFile::xcoff_symbol_iterator_range XCOFFObjectFile::symbols() const {
return xcoff_symbol_iterator_range(symbol_begin(), symbol_end());
}

section_iterator XCOFFObjectFile::section_begin() const {
DataRefImpl DRI;
DRI.p = getSectionHeaderTableAddress();
Expand Down Expand Up @@ -1248,15 +1252,15 @@ bool XCOFFSymbolRef::isFunction() const {
return false;

const int16_t SectNum = getSectionNumber();
Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
Expected<DataRefImpl> SI = getObject()->getSectionByNum(SectNum);
if (!SI) {
// If we could not get the section, then this symbol should not be
// a function. So consume the error and return `false` to move on.
consumeError(SI.takeError());
return false;
}

return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
return (getObject()->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
}

bool XCOFFSymbolRef::isCsectSymbol() const {
Expand All @@ -1275,13 +1279,13 @@ Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
if (auto Err = NameOrErr.takeError())
return std::move(Err);

uint32_t SymbolIdx = OwningObjectPtr->getSymbolIndex(getEntryAddress());
uint32_t SymbolIdx = getObject()->getSymbolIndex(getEntryAddress());
if (!NumberOfAuxEntries) {
return createError("csect symbol \"" + *NameOrErr + "\" with index " +
Twine(SymbolIdx) + " contains no auxiliary entry");
}

if (!OwningObjectPtr->is64Bit()) {
if (!getObject()->is64Bit()) {
// In XCOFF32, the csect auxilliary entry is always the last auxiliary
// entry for the symbol.
uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
Expand All @@ -1294,10 +1298,10 @@ Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) {
uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
getEntryAddress(), Index);
if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) ==
if (*getObject()->getSymbolAuxType(AuxAddr) ==
XCOFF::SymbolAuxType::AUX_CSECT) {
#ifndef NDEBUG
OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
getObject()->checkSymbolEntryPointer(AuxAddr);
#endif
return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr));
}
Expand All @@ -1314,14 +1318,15 @@ Expected<StringRef> XCOFFSymbolRef::getName() const {
if (getStorageClass() & 0x80)
return StringRef("Unimplemented Debug Name");

if (Entry32) {
if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
return generateXCOFFFixedNameStringRef(Entry32->SymbolName);
if (!getObject()->is64Bit()) {
if (getSymbol32()->NameInStrTbl.Magic !=
XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
return generateXCOFFFixedNameStringRef(getSymbol32()->SymbolName);

return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset);
return getObject()->getStringTableEntry(getSymbol32()->NameInStrTbl.Offset);
}

return OwningObjectPtr->getStringTableEntry(Entry64->Offset);
return getObject()->getStringTableEntry(getSymbol64()->Offset);
}

// Explictly instantiate template classes.
Expand Down
9 changes: 3 additions & 6 deletions llvm/test/DebugInfo/Symbolize/XCOFF/xcoff-symbolize-data.ll
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,20 @@
; CHECK-EMPTY:

;; Test a function scope static variable.
;; FIXME: fix the wrong size 152
; CHECK: f()::function_global
; CHECK-NEXT: 144 152
; CHECK-NEXT: 144 4
; CHECK-NEXT: /t.cpp:8
; CHECK-EMPTY:

;; Test a global scope static variable that is used in current compilation unit.
;; FIXME: fix the wrong size 152
; CHECK: beta
; CHECK-NEXT: 148 152
; CHECK-NEXT: 148 4
; CHECK-NEXT: /t.cpp:13
; CHECK-EMPTY:

;; Test another global scope static variable that is used in current compilation unit.
;; FIXME: fix the wrong size 152
; CHECK: alpha
; CHECK-NEXT: 152 152
; CHECK-NEXT: 152 4
; CHECK-NEXT: /t.cpp:12
; CHECK-EMPTY:

Expand Down