diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h index 5f51aacfabc08..be468e888aa5c 100644 --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -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" @@ -23,6 +24,8 @@ namespace llvm { namespace object { +class xcoff_symbol_iterator; + struct XCOFFFileHeader32 { support::ubig16_t Magic; support::ubig16_t NumberOfSections; @@ -576,6 +579,10 @@ class XCOFFObjectFile : public ObjectFile { Expected 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_range symbols() const; + bool is64Bit() const override; Expected getSymbolName(DataRefImpl Symb) const override; Expected getSymbolAddress(DataRefImpl Symb) const override; @@ -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(SymEntDataRef.p); - else - Entry32 = reinterpret_cast(SymEntDataRef.p); + const XCOFFSymbolEntry32 *getSymbol32() const { + return reinterpret_cast(getRawDataRefImpl().p); + } + const XCOFFSymbolEntry64 *getSymbol64() const { + return reinterpret_cast(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(getRawDataRefImpl().p) + ->Value; + } - uint32_t getValue32() const { return Entry32->Value; } + uint64_t getValue64() const { + return reinterpret_cast(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(getRawDataRefImpl().p)->X \ + : reinterpret_cast(getRawDataRefImpl().p)->X int16_t getSectionNumber() const { return GETVALUE(SectionNumber); } @@ -812,8 +833,7 @@ class XCOFFSymbolRef { #undef GETVALUE uintptr_t getEntryAddress() const { - return Entry32 ? reinterpret_cast(Entry32) - : reinterpret_cast(Entry64); + return getRawDataRefImpl().p; } Expected getName() const; @@ -822,9 +842,23 @@ class XCOFFSymbolRef { Expected getXCOFFCsectAuxRef() const; private: - const XCOFFObjectFile *OwningObjectPtr; - const XCOFFSymbolEntry32 *Entry32 = nullptr; - const XCOFFSymbolEntry64 *Entry64 = nullptr; + const XCOFFObjectFile *getObject() const { + return cast(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(symbol_iterator::operator->()); + } + + const XCOFFSymbolRef &operator*() const { + return static_cast(symbol_iterator::operator*()); + } }; class TBVectorExt { diff --git a/llvm/lib/Object/SymbolSize.cpp b/llvm/lib/Object/SymbolSize.cpp index f93a5f7d9bd54..c4f30b1072d52 100644 --- a/llvm/lib/Object/SymbolSize.cpp +++ b/llvm/lib/Object/SymbolSize.cpp @@ -59,6 +59,13 @@ llvm::object::computeSymbolSizes(const ObjectFile &O) { return Ret; } + if (const auto *E = dyn_cast(&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 Addresses; diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp index fa4917e354e92..4c192aa37a7ec 100644 --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -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(); @@ -1248,7 +1252,7 @@ bool XCOFFSymbolRef::isFunction() const { return false; const int16_t SectNum = getSectionNumber(); - Expected SI = OwningObjectPtr->getSectionByNum(SectNum); + Expected 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. @@ -1256,7 +1260,7 @@ bool XCOFFSymbolRef::isFunction() const { return false; } - return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); + return (getObject()->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); } bool XCOFFSymbolRef::isCsectSymbol() const { @@ -1275,13 +1279,13 @@ Expected 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( @@ -1294,10 +1298,10 @@ Expected 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(AuxAddr)); } @@ -1314,14 +1318,15 @@ Expected 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. diff --git a/llvm/test/DebugInfo/Symbolize/XCOFF/xcoff-symbolize-data.ll b/llvm/test/DebugInfo/Symbolize/XCOFF/xcoff-symbolize-data.ll index 968c175ffdc6c..5432b59d583ba 100644 --- a/llvm/test/DebugInfo/Symbolize/XCOFF/xcoff-symbolize-data.ll +++ b/llvm/test/DebugInfo/Symbolize/XCOFF/xcoff-symbolize-data.ll @@ -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: