[XCOFF][AIX] Generate symbol table entries with llvm-readobj

Summary:

This patch implements main entry and auxiliary entries of symbol table generation for llvm-readobj on AIX.
The source code of aix_xcoff_xlc_test8.o (compile with xlc) is:

-bash-4.2$ cat test8.c
extern int i;
extern int TestforXcoff;
extern int fun(int i);
static int static_i;
char* p="abcd";
int fun1(int j) {
  static_i++;
  j++;
  j=j+*p;
  return j;
}
int main() {
  i++;
  fun(i);
  return fun1(i);
}

Patch provided by DiggerLin

Differential Revision: https://reviews.llvm.org/D65240

llvm-svn: 370097
This commit is contained in:
Jason Liu 2019-08-27 18:54:46 +00:00
parent 559ae14c9b
commit 7c72e82b25
6 changed files with 937 additions and 28 deletions

View File

@ -19,12 +19,13 @@ namespace llvm {
namespace XCOFF {
// Constants used in the XCOFF definition.
enum { NameSize = 8 };
enum { FileNamePadSize = 6, NameSize = 8, SymbolTableEntrySize = 18 };
enum ReservedSectionNum { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 };
// x_smclas field of x_csect from system header: /usr/include/syms.h
/// Storage Mapping Class definitions.
enum StorageMappingClass {
enum StorageMappingClass : uint8_t {
// READ ONLY CLASSES
XMC_PR = 0, ///< Program Code
XMC_RO = 1, ///< Read Only Constant
@ -170,6 +171,24 @@ struct SectionHeader32 {
int32_t Flags;
};
enum CFileStringType : uint8_t {
XFT_FN = 0, ///< Specifies the source-file name.
XFT_CT = 1, ///< Specifies the compiler time stamp.
XFT_CV = 2, ///< Specifies the compiler version number.
XFT_CD = 128 ///< Specifies compiler-defined information.
};
enum CFileLangId : uint8_t {
TB_C = 0, ///< C language.
TB_CPLUSPLUS = 9 ///< C++ language.
};
enum CFileCpuId : uint8_t {
TCPU_PPC64 = 2, ///< PowerPC common architecture 64-bit mode.
TCPU_COM = 3, ///< POWER and PowerPC architecture common.
TCPU_970 = 19 ///< PPC970 - PowerPC 64-bit architecture.
};
} // end namespace XCOFF
} // end namespace llvm

View File

@ -112,6 +112,38 @@ struct XCOFFStringTable {
const char *Data;
};
struct XCOFFCsectAuxEnt32 {
support::ubig32_t SectionLen;
support::ubig32_t ParameterHashIndex;
support::ubig16_t TypeChkSectNum;
uint8_t SymbolAlignmentAndType;
XCOFF::StorageMappingClass StorageMappingClass;
support::ubig32_t StabInfoIndex;
support::ubig16_t StabSectNum;
};
struct XCOFFFileAuxEnt {
typedef struct {
support::big32_t Magic; // Zero indicates name in string table.
support::ubig32_t Offset;
char NamePad[XCOFF::FileNamePadSize];
} NameInStrTblType;
union {
char Name[XCOFF::NameSize + XCOFF::FileNamePadSize];
NameInStrTblType NameInStrTbl;
};
XCOFF::CFileStringType Type;
uint8_t ReservedZeros[2];
uint8_t AuxType; // 64-bit XCOFF file only.
};
struct XCOFFSectAuxEntForStat {
support::ubig32_t SectionLength;
support::ubig16_t NumberOfRelocEnt;
support::ubig16_t NumberOfLineNum;
uint8_t Pad[10];
};
class XCOFFObjectFile : public ObjectFile {
private:
const void *FileHeader = nullptr;
@ -131,18 +163,18 @@ private:
const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
uintptr_t getSectionHeaderTableAddress() const;
uintptr_t getEndOfSymbolTableAddress() const;
// This returns a pointer to the start of the storage for the name field of
// the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
// null-terminated.
const char *getSectionNameInternal(DataRefImpl Sec) const;
int32_t getSectionFlags(DataRefImpl Sec) const;
// This function returns string table entry.
Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
static bool isReservedSectionNumber(int16_t SectionNumber);
Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
// Constructor and "create" factory function. The constructor is only a thin
// wrapper around the base constructor. The "create" function fills out the
@ -160,6 +192,8 @@ private:
friend Expected<std::unique_ptr<ObjectFile>>
ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
public:
// Interface inherited from base classes.
void moveSymbolNext(DataRefImpl &Symb) const override;
@ -238,15 +272,41 @@ public:
uint32_t getLogicalNumberOfSymbolTableEntries32() const;
uint32_t getNumberOfSymbolTableEntries64() const;
uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
uint16_t getOptionalHeaderSize() const;
uint16_t getFlags() const;
// Section header table related interfaces.
ArrayRef<XCOFFSectionHeader32> sections32() const;
ArrayRef<XCOFFSectionHeader64> sections64() const;
int32_t getSectionFlags(DataRefImpl Sec) const;
Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
}; // XCOFFObjectFile
class XCOFFSymbolRef {
const DataRefImpl SymEntDataRef;
const XCOFFObjectFile *const OwningObjectPtr;
public:
XCOFFSymbolRef(DataRefImpl SymEntDataRef,
const XCOFFObjectFile *OwningObjectPtr)
: SymEntDataRef(SymEntDataRef), OwningObjectPtr(OwningObjectPtr){};
XCOFF::StorageClass getStorageClass() const;
uint8_t getNumberOfAuxEntries() const;
const XCOFFCsectAuxEnt32 *getXCOFFCsectAuxEnt32() const;
uint16_t getType() const;
int16_t getSectionNumber() const;
bool hasCsectAuxEnt() const;
bool isFunction() const;
};
} // namespace object
} // namespace llvm

View File

@ -17,6 +17,11 @@
namespace llvm {
namespace object {
enum {
FUNCTION_SYM = 0x20,
SYM_TYPE_MASK = 0x07
};
// Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
// 'M'. Returns a pointer to the underlying object on success.
template <typename T>
@ -37,7 +42,7 @@ template <typename T> static const T *viewAs(uintptr_t in) {
return reinterpret_cast<const T *>(in);
}
static StringRef generateStringRef(const char *Name) {
static StringRef generateXCOFFFixedNameStringRef(const char *Name) {
auto NulCharPtr =
static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize));
return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
@ -79,6 +84,9 @@ XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
#ifndef NDEBUG
checkSymbolEntryPointer(Ref.p);
#endif
auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p);
return SymEntPtr;
}
@ -108,23 +116,19 @@ XCOFFObjectFile::sectionHeaderTable64() const {
void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
#ifndef NDEBUG
// This function is used by basic_symbol_iterator, which allows to
// point to the end-of-symbol-table address.
if (reinterpret_cast<uintptr_t>(SymEntPtr) != getEndOfSymbolTableAddress())
checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(SymEntPtr));
#endif
Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
}
Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
return generateStringRef(SymEntPtr->SymbolName);
// A storage class value with the high-order bit on indicates that the name is
// a symbolic debugger stabstring.
if (SymEntPtr->StorageClass & 0x80)
return StringRef("Unimplemented Debug Name");
uint32_t Offset = SymEntPtr->NameInStrTbl.Offset;
// The byte offset is relative to the start of the string table
// or .debug section. A byte offset value of 0 is a null or zero-length symbol
Expected<StringRef>
XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
// The byte offset is relative to the start of the string table.
// A byte offset value of 0 is a null or zero-length symbol
// name. A byte offset in the range 1 to 3 (inclusive) points into the length
// field; as a soft-error recovery mechanism, we treat such cases as having an
// offset of 0.
@ -134,10 +138,32 @@ Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
if (StringTable.Data != nullptr && StringTable.Size > Offset)
return (StringTable.Data + Offset);
return make_error<GenericBinaryError>("Symbol Name parse failed",
return make_error<GenericBinaryError>("Bad offset for string table entry",
object_error::parse_failed);
}
Expected<StringRef>
XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
if (CFileEntPtr->NameInStrTbl.Magic !=
XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
}
Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
// A storage class value with the high-order bit on indicates that the name is
// a symbolic debugger stabstring.
if (SymEntPtr->StorageClass & 0x80)
return StringRef("Unimplemented Debug Name");
if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
return generateXCOFFFixedNameStringRef(SymEntPtr->SymbolName);
return getStringTableEntry(SymEntPtr->NameInStrTbl.Offset);
}
Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
uint64_t Result = 0;
llvm_unreachable("Not yet implemented!");
@ -145,6 +171,7 @@ Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
}
uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
return toSymbolEntry(Symb)->Value;
}
@ -181,7 +208,7 @@ void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
}
Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
return generateStringRef(getSectionNameInternal(Sec));
return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
}
uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
@ -389,7 +416,8 @@ XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
default:
Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
if (SecRef)
return generateStringRef(getSectionNameInternal(SecRef.get()));
return generateXCOFFFixedNameStringRef(
getSectionNameInternal(SecRef.get()));
return SecRef.takeError();
}
}
@ -437,6 +465,35 @@ uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
return fileHeader64()->NumberOfSymTableEntries;
}
uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
uint32_t NumberOfSymTableEntries =
is64Bit() ? getNumberOfSymbolTableEntries64()
: getLogicalNumberOfSymbolTableEntries32();
return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
}
void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
report_fatal_error("Symbol table entry is outside of symbol table.");
if (SymbolEntPtr >= getEndOfSymbolTableAddress())
report_fatal_error("Symbol table entry is outside of symbol table.");
ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
reinterpret_cast<const char *>(SymbolTblPtr);
if (Offset % XCOFF::SymbolTableEntrySize != 0)
report_fatal_error(
"Symbol table entry position is not valid inside of symbol table.");
}
uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
return (reinterpret_cast<const char *>(SymbolEntPtr) -
reinterpret_cast<const char *>(SymbolTblPtr)) /
XCOFF::SymbolTableEntrySize;
}
uint16_t XCOFFObjectFile::getFlags() const {
return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
}
@ -568,11 +625,77 @@ ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
}
StringRef XCOFFSectionHeader32::getName() const {
return generateStringRef(Name);
return generateXCOFFFixedNameStringRef(Name);
}
StringRef XCOFFSectionHeader64::getName() const {
return generateStringRef(Name);
return generateXCOFFFixedNameStringRef(Name);
}
XCOFF::StorageClass XCOFFSymbolRef::getStorageClass() const {
return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->StorageClass;
}
uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const {
return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries;
}
const XCOFFCsectAuxEnt32 *XCOFFSymbolRef::getXCOFFCsectAuxEnt32() const {
assert(!OwningObjectPtr->is64Bit() &&
"32-bit interface called on 64-bit object file.");
assert(hasCsectAuxEnt() && "No Csect Auxiliary Entry is found.");
// In XCOFF32, the csect auxilliary entry is always the last auxiliary
// entry for the symbol.
uintptr_t AuxAddr = getWithOffset(
SymEntDataRef.p, XCOFF::SymbolTableEntrySize * getNumberOfAuxEntries());
#ifndef NDEBUG
OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
#endif
return reinterpret_cast<const XCOFFCsectAuxEnt32 *>(AuxAddr);
}
uint16_t XCOFFSymbolRef::getType() const {
return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SymbolType;
}
int16_t XCOFFSymbolRef::getSectionNumber() const {
return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber;
}
bool XCOFFSymbolRef::hasCsectAuxEnt() const {
XCOFF::StorageClass SC = getStorageClass();
return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
SC == XCOFF::C_HIDEXT);
}
bool XCOFFSymbolRef::isFunction() const {
if (OwningObjectPtr->is64Bit())
report_fatal_error("64-bit support is unimplemented yet.");
if (getType() & FUNCTION_SYM)
return true;
if (!hasCsectAuxEnt())
return false;
const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32();
// A function definition should be a label definition.
if ((CsectAuxEnt->SymbolAlignmentAndType & SYM_TYPE_MASK) != XCOFF::XTY_LD)
return false;
if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR)
return false;
int16_t SectNum = getSectionNumber();
Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
if (!SI)
return false;
return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
}
} // namespace object

View File

@ -0,0 +1,446 @@
# This file tests the ability of llvm-readobj to display the symbol table for a
# 32-bit XCOFF object file.
RUN: llvm-readobj --symbols %p/Inputs/aix_xcoff_xlc_test8.o | \
RUN: FileCheck --check-prefix=SYMBOL32 %s
SYMBOL32: File: {{.*}}aix_xcoff_xlc_test8.o
SYMBOL32-NEXT: Format: aixcoff-rs6000
SYMBOL32-NEXT: Arch: powerpc
SYMBOL32-NEXT: AddressSize: 32bit
SYMBOL32-NEXT: Symbols [
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 0
SYMBOL32-NEXT: Name: .file
SYMBOL32-NEXT: Value (SymbolTableIndex): 0x0
SYMBOL32-NEXT: Section: N_DEBUG
SYMBOL32-NEXT: Source Language ID: TB_C (0x0)
SYMBOL32-NEXT: CPU Version ID: TCPU_COM (0x3)
SYMBOL32-NEXT: StorageClass: C_FILE (0x67)
SYMBOL32-NEXT: NumberOfAuxEntries: 3
SYMBOL32-NEXT: File Auxiliary Entry {
SYMBOL32-NEXT: Index: 1
SYMBOL32-NEXT: Name: test8.c
SYMBOL32-NEXT: Type: XFT_FN (0x0)
SYMBOL32-NEXT: }
SYMBOL32-NEXT: File Auxiliary Entry {
SYMBOL32-NEXT: Index: 2
SYMBOL32-NEXT: Name: Sun Apr 28 15:56:49 2019
SYMBOL32-NEXT: Type: XFT_CT (0x1)
SYMBOL32-NEXT: }
SYMBOL32-NEXT: File Auxiliary Entry {
SYMBOL32-NEXT: Index: 3
SYMBOL32-NEXT: Name: IBM XL C for AIX, Version 16.1.0.2
SYMBOL32-NEXT: Type: XFT_CV (0x2)
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 4
SYMBOL32-NEXT: Name: .text
SYMBOL32-NEXT: Value (RelocatableAddress): 0x0
SYMBOL32-NEXT: Section: .text
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_STAT (0x3)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: Sect Auxiliary Entry For Stat {
SYMBOL32-NEXT: Index: 5
SYMBOL32-NEXT: SectionLength: 256
SYMBOL32-NEXT: NumberOfRelocEnt: 4
SYMBOL32-NEXT: NumberOfLineNum: 0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 6
SYMBOL32-NEXT: Name: .data
SYMBOL32-NEXT: Value (RelocatableAddress): 0x100
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_STAT (0x3)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: Sect Auxiliary Entry For Stat {
SYMBOL32-NEXT: Index: 7
SYMBOL32-NEXT: SectionLength: 60
SYMBOL32-NEXT: NumberOfRelocEnt: 11
SYMBOL32-NEXT: NumberOfLineNum: 0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 8
SYMBOL32-NEXT: Name: .bss
SYMBOL32-NEXT: Value (RelocatableAddress): 0x13C
SYMBOL32-NEXT: Section: .bss
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_STAT (0x3)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: Sect Auxiliary Entry For Stat {
SYMBOL32-NEXT: Index: 9
SYMBOL32-NEXT: SectionLength: 4
SYMBOL32-NEXT: NumberOfRelocEnt: 0
SYMBOL32-NEXT: NumberOfLineNum: 0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 10
SYMBOL32-NEXT: Name:
SYMBOL32-NEXT: Value (RelocatableAddress): 0x0
SYMBOL32-NEXT: Section: .text
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 11
SYMBOL32-NEXT: SectionLen: 256
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 7
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_PR (0x0)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 12
SYMBOL32-NEXT: Name: .fun1
SYMBOL32-NEXT: Value (RelocatableAddress): 0x0
SYMBOL32-NEXT: Section: .text
SYMBOL32-NEXT: Type: 0x20
SYMBOL32-NEXT: StorageClass: C_EXT (0x2)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 13
SYMBOL32-NEXT: ContainingCsectSymbolIndex: 10
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 0
SYMBOL32-NEXT: SymbolType: XTY_LD (0x2)
SYMBOL32-NEXT: StorageMappingClass: XMC_PR (0x0)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 14
SYMBOL32-NEXT: Name: .main
SYMBOL32-NEXT: Value (RelocatableAddress): 0x60
SYMBOL32-NEXT: Section: .text
SYMBOL32-NEXT: Type: 0x20
SYMBOL32-NEXT: StorageClass: C_EXT (0x2)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 15
SYMBOL32-NEXT: ContainingCsectSymbolIndex: 10
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 0
SYMBOL32-NEXT: SymbolType: XTY_LD (0x2)
SYMBOL32-NEXT: StorageMappingClass: XMC_PR (0x0)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 16
SYMBOL32-NEXT: Name: TOC
SYMBOL32-NEXT: Value (RelocatableAddress): 0x100
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 17
SYMBOL32-NEXT: SectionLen: 0
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_TC0 (0xF)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 18
SYMBOL32-NEXT: Name:
SYMBOL32-NEXT: Value (RelocatableAddress): 0x114
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 19
SYMBOL32-NEXT: SectionLen: 4
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 20
SYMBOL32-NEXT: Name:
SYMBOL32-NEXT: Value (RelocatableAddress): 0x134
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 21
SYMBOL32-NEXT: SectionLen: 5
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 3
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_RO (0x1)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 22
SYMBOL32-NEXT: Name: _$STATIC_BSS
SYMBOL32-NEXT: Value (RelocatableAddress): 0x13C
SYMBOL32-NEXT: Section: .bss
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 23
SYMBOL32-NEXT: SectionLen: 4
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_CM (0x3)
SYMBOL32-NEXT: StorageMappingClass: XMC_RW (0x5)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 24
SYMBOL32-NEXT: Name: _$STATIC_BSS
SYMBOL32-NEXT: Value (RelocatableAddress): 0x104
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 25
SYMBOL32-NEXT: SectionLen: 4
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 26
SYMBOL32-NEXT: Name: fun1
SYMBOL32-NEXT: Value (RelocatableAddress): 0x118
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_EXT (0x2)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 27
SYMBOL32-NEXT: SectionLen: 12
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_DS (0xA)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 28
SYMBOL32-NEXT: Name: fun1
SYMBOL32-NEXT: Value (RelocatableAddress): 0x100
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 29
SYMBOL32-NEXT: SectionLen: 4
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 30
SYMBOL32-NEXT: Name: p
SYMBOL32-NEXT: Value (RelocatableAddress): 0x130
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_EXT (0x2)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 31
SYMBOL32-NEXT: SectionLen: 4
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_RW (0x5)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 32
SYMBOL32-NEXT: Name: p
SYMBOL32-NEXT: Value (RelocatableAddress): 0x108
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 33
SYMBOL32-NEXT: SectionLen: 4
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 34
SYMBOL32-NEXT: Name: main
SYMBOL32-NEXT: Value (RelocatableAddress): 0x124
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_EXT (0x2)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 35
SYMBOL32-NEXT: SectionLen: 12
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_DS (0xA)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 36
SYMBOL32-NEXT: Name: main
SYMBOL32-NEXT: Value (RelocatableAddress): 0x10C
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 37
SYMBOL32-NEXT: SectionLen: 4
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 38
SYMBOL32-NEXT: Name: i
SYMBOL32-NEXT: Value (RelocatableAddress): 0x0
SYMBOL32-NEXT: Section: N_UNDEF
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_EXT (0x2)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 39
SYMBOL32-NEXT: SectionLen: 0
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 0
SYMBOL32-NEXT: SymbolType: XTY_ER (0x0)
SYMBOL32-NEXT: StorageMappingClass: XMC_UA (0x4)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 40
SYMBOL32-NEXT: Name: i
SYMBOL32-NEXT: Value (RelocatableAddress): 0x110
SYMBOL32-NEXT: Section: .data
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 41
SYMBOL32-NEXT: SectionLen: 4
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 2
SYMBOL32-NEXT: SymbolType: XTY_SD (0x1)
SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: Symbol {
SYMBOL32-NEXT: Index: 42
SYMBOL32-NEXT: Name: .fun
SYMBOL32-NEXT: Value (RelocatableAddress): 0x0
SYMBOL32-NEXT: Section: N_UNDEF
SYMBOL32-NEXT: Type: 0x0
SYMBOL32-NEXT: StorageClass: C_EXT (0x2)
SYMBOL32-NEXT: NumberOfAuxEntries: 1
SYMBOL32-NEXT: CSECT Auxiliary Entry {
SYMBOL32-NEXT: Index: 43
SYMBOL32-NEXT: SectionLen: 0
SYMBOL32-NEXT: ParameterHashIndex: 0x0
SYMBOL32-NEXT: TypeChkSectNum: 0x0
SYMBOL32-NEXT: SymbolAlignmentLog2: 0
SYMBOL32-NEXT: SymbolType: XTY_ER (0x0)
SYMBOL32-NEXT: StorageMappingClass: XMC_PR (0x0)
SYMBOL32-NEXT: StabInfoIndex: 0x0
SYMBOL32-NEXT: StabSectNum: 0x0
SYMBOL32-NEXT: }
SYMBOL32-NEXT: }
SYMBOL32-NEXT: ]
# The object file used is generated by the following source file
# and command on AIX:
#
# > cat test8.c
#
# extern int i;
# extern int TestforXcoff;
# extern int fun(int i);
# static int static_i;
# char* p="abcd";
# int fun1(int j) {
# static_i++;
# j++;
# j=j+*p;
# return j;
# }
#
# int main() {
# i++;
# fun(i);
# return fun1(i);
# }
#
# > xlc -c test8.c -o aix_xcoff_xlc_test8.o

View File

@ -22,6 +22,12 @@ using namespace object;
namespace {
class XCOFFDumper : public ObjDumper {
enum {
SymbolTypeMask = 0x07,
SymbolAlignmentMask = 0xF8,
SymbolAlignmentBitOffset = 3
};
public:
XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
: ObjDumper(Writer), Obj(Obj) {}
@ -37,11 +43,14 @@ public:
private:
template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
const XCOFFObjectFile &Obj;
void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
void printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr);
void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
void printSymbol(const SymbolRef &);
// Least significant 3 bits are reserved.
static constexpr unsigned SectionFlagsReservedMask = 0x7;
const XCOFFObjectFile &Obj;
};
} // anonymous namespace
@ -103,8 +112,260 @@ void XCOFFDumper::printRelocations() {
llvm_unreachable("Unimplemented functionality for XCOFFDumper");
}
static const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
#define ECase(X) \
{ #X, XCOFF::X }
ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)
#undef ECase
};
void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
if (Obj.is64Bit())
report_fatal_error(
"Printing for File Auxiliary Entry in 64-bit is unimplemented.");
StringRef FileName =
unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
DictScope SymDs(W, "File Auxiliary Entry");
W.printNumber("Index",
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
W.printString("Name", FileName);
W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
makeArrayRef(FileStringType));
}
static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
{
#define ECase(X) \
{ #X, XCOFF::X }
ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB),
ECase(XMC_GL), ECase(XMC_XO), ECase(XMC_SV),
ECase(XMC_SV64), ECase(XMC_SV3264), ECase(XMC_TI),
ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0),
ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS),
ECase(XMC_UA), ECase(XMC_BS), ECase(XMC_UC),
ECase(XMC_TL), ECase(XMC_TE)
#undef ECase
};
static const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
#define ECase(X) \
{ #X, XCOFF::X }
ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
#undef ECase
};
void XCOFFDumper::printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr) {
assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
DictScope SymDs(W, "CSECT Auxiliary Entry");
W.printNumber("Index",
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
if ((AuxEntPtr->SymbolAlignmentAndType & SymbolTypeMask) == XCOFF::XTY_LD)
W.printNumber("ContainingCsectSymbolIndex", AuxEntPtr->SectionLen);
else
W.printNumber("SectionLen", AuxEntPtr->SectionLen);
W.printHex("ParameterHashIndex", AuxEntPtr->ParameterHashIndex);
W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum);
// Print out symbol alignment and type.
W.printNumber("SymbolAlignmentLog2",
(AuxEntPtr->SymbolAlignmentAndType & SymbolAlignmentMask) >>
SymbolAlignmentBitOffset);
W.printEnum("SymbolType", AuxEntPtr->SymbolAlignmentAndType & SymbolTypeMask,
makeArrayRef(CsectSymbolTypeClass));
W.printEnum("StorageMappingClass",
static_cast<uint8_t>(AuxEntPtr->StorageMappingClass),
makeArrayRef(CsectStorageMappingClass));
W.printHex("StabInfoIndex", AuxEntPtr->StabInfoIndex);
W.printHex("StabSectNum", AuxEntPtr->StabSectNum);
}
void XCOFFDumper::printSectAuxEntForStat(
const XCOFFSectAuxEntForStat *AuxEntPtr) {
assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
W.printNumber("Index",
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
W.printNumber("SectionLength", AuxEntPtr->SectionLength);
// Unlike the corresponding fields in the section header, NumberOfRelocEnt
// and NumberOfLineNum do not handle values greater than 65535.
W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
}
static const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
#define ECase(X) \
{ #X, XCOFF::X }
ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT),
ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL),
ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU),
ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG),
ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK),
ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE),
ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL),
ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF),
ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM),
ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM),
ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY),
ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS),
ECase(C_STTLS), ECase(C_EFCN)
#undef ECase
};
static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
switch (SC) {
case XCOFF::C_EXT:
case XCOFF::C_WEAKEXT:
case XCOFF::C_HIDEXT:
case XCOFF::C_STAT:
return "Value (RelocatableAddress)";
case XCOFF::C_FILE:
return "Value (SymbolTableIndex)";
case XCOFF::C_FCN:
case XCOFF::C_BLOCK:
case XCOFF::C_FUN:
case XCOFF::C_STSYM:
case XCOFF::C_BINCL:
case XCOFF::C_EINCL:
case XCOFF::C_INFO:
case XCOFF::C_BSTAT:
case XCOFF::C_LSYM:
case XCOFF::C_PSYM:
case XCOFF::C_RPSYM:
case XCOFF::C_RSYM:
case XCOFF::C_ECOML:
case XCOFF::C_DWARF:
assert(false && "This StorageClass for the symbol is not yet implemented.");
default:
return "Value";
}
}
static const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
#define ECase(X) \
{ #X, XCOFF::X }
ECase(TB_C), ECase(TB_CPLUSPLUS)
#undef ECase
};
static const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
#define ECase(X) \
{ #X, XCOFF::X }
ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
#undef ECase
};
void XCOFFDumper::printSymbol(const SymbolRef &S) {
if (Obj.is64Bit())
report_fatal_error("64-bit support is unimplemented.");
DataRefImpl SymbolDRI = S.getRawDataRefImpl();
const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
XCOFFSymbolRef XCOFFSymRef(SymbolDRI, &Obj);
uint8_t NumberOfAuxEntries = XCOFFSymRef.getNumberOfAuxEntries();
DictScope SymDs(W, "Symbol");
StringRef SymbolName =
unwrapOrError(Obj.getFileName(), Obj.getSymbolName(SymbolDRI));
W.printNumber("Index",
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(SymbolEntPtr)));
W.printString("Name", SymbolName);
W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass),
SymbolEntPtr->Value);
StringRef SectionName =
unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntPtr));
W.printString("Section", SectionName);
if (XCOFFSymRef.getStorageClass() == XCOFF::C_FILE) {
W.printEnum("Source Language ID",
SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId,
makeArrayRef(CFileLangIdClass));
W.printEnum("CPU Version ID",
SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId,
makeArrayRef(CFileCpuIdClass));
} else
W.printHex("Type", SymbolEntPtr->SymbolType);
W.printEnum("StorageClass", static_cast<uint8_t>(SymbolEntPtr->StorageClass),
makeArrayRef(SymStorageClass));
W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries);
if (NumberOfAuxEntries == 0)
return;
switch (XCOFFSymRef.getStorageClass()) {
case XCOFF::C_FILE:
// If the symbol is C_FILE and has auxiliary entries...
for (int i = 1; i <= NumberOfAuxEntries; i++) {
const XCOFFFileAuxEnt *FileAuxEntPtr =
reinterpret_cast<const XCOFFFileAuxEnt *>(SymbolEntPtr + i);
#ifndef NDEBUG
Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(FileAuxEntPtr));
#endif
printFileAuxEnt(FileAuxEntPtr);
}
break;
case XCOFF::C_EXT:
case XCOFF::C_WEAKEXT:
case XCOFF::C_HIDEXT:
// If the symbol is for a function, and it has more than 1 auxiliary entry,
// then one of them must be function auxiliary entry which we do not
// support yet.
if (XCOFFSymRef.isFunction() && NumberOfAuxEntries >= 2)
report_fatal_error("Function auxiliary entry printing is unimplemented.");
// If there is more than 1 auxiliary entry, instead of printing out
// error information, print out the raw Auxiliary entry from 1st till
// the last - 1. The last one must be a CSECT Auxiliary Entry.
for (int i = 1; i < NumberOfAuxEntries; i++) {
W.startLine() << "!Unexpected raw auxiliary entry data:\n";
W.startLine() << format_bytes(
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
XCOFF::SymbolTableEntrySize));
}
// The symbol's last auxiliary entry is a CSECT Auxiliary Entry.
printCsectAuxEnt32(XCOFFSymRef.getXCOFFCsectAuxEnt32());
break;
case XCOFF::C_STAT:
if (NumberOfAuxEntries > 1)
report_fatal_error(
"C_STAT symbol should not have more than 1 auxiliary entry.");
const XCOFFSectAuxEntForStat *StatAuxEntPtr;
StatAuxEntPtr =
reinterpret_cast<const XCOFFSectAuxEntForStat *>(SymbolEntPtr + 1);
#ifndef NDEBUG
Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(StatAuxEntPtr));
#endif
printSectAuxEntForStat(StatAuxEntPtr);
break;
case XCOFF::C_DWARF:
case XCOFF::C_BLOCK:
case XCOFF::C_FCN:
report_fatal_error("Symbol table entry printing for this storage class "
"type is unimplemented.");
break;
default:
for (int i = 1; i <= NumberOfAuxEntries; i++) {
W.startLine() << "!Unexpected raw auxiliary entry data:\n";
W.startLine() << format_bytes(
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
XCOFF::SymbolTableEntrySize));
}
break;
}
}
void XCOFFDumper::printSymbols() {
llvm_unreachable("Unimplemented functionality for XCOFFDumper");
ListScope Group(W, "Symbols");
for (const SymbolRef &S : Obj.symbols())
printSymbol(S);
}
void XCOFFDumper::printDynamicSymbols() {