aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/XCOFFObjectFile.cpp
diff options
context:
space:
mode:
authorjasonliu <jasonliu.development@gmail.com>2021-06-07 14:52:55 +0000
committerjasonliu <jasonliu.development@gmail.com>2021-06-07 17:24:13 +0000
commit8e84311a84b35ced5c18c3af8a802f7d2aa5c8a0 (patch)
treecbfa07dedf281ee9f063326aa61577c23d334255 /llvm/lib/Object/XCOFFObjectFile.cpp
parent4675beaa2181b6ccb1a37fd49b51a45490023974 (diff)
downloadllvm-8e84311a84b35ced5c18c3af8a802f7d2aa5c8a0.zip
llvm-8e84311a84b35ced5c18c3af8a802f7d2aa5c8a0.tar.gz
llvm-8e84311a84b35ced5c18c3af8a802f7d2aa5c8a0.tar.bz2
[XCOFF][AIX] Enable tooling support for 64 bit symbol table parsing
Add in the ability of parsing symbol table for 64 bit object. Reviewed By: jhenderson, DiggerLin Differential Revision: https://reviews.llvm.org/D85774
Diffstat (limited to 'llvm/lib/Object/XCOFFObjectFile.cpp')
-rw-r--r--llvm/lib/Object/XCOFFObjectFile.cpp231
1 files changed, 130 insertions, 101 deletions
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index 74b10fa..86815539 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -24,8 +24,8 @@ using namespace XCOFF;
namespace object {
static const uint8_t FunctionSym = 0x20;
-static const uint8_t SymTypeMask = 0x07;
static const uint16_t NoRelMask = 0x0001;
+static const size_t SymbolAuxTypeOffset = 17;
// Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
// 'M'. Returns a pointer to the underlying object on success.
@@ -83,6 +83,19 @@ uint8_t XCOFFRelocation32::getRelocatedLength() const {
return (Info & XR_BIASED_LENGTH_MASK) + 1;
}
+uintptr_t
+XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
+ uint32_t Distance) {
+ return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize);
+}
+
+const XCOFF::SymbolAuxType *
+XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const {
+ assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
+ return viewAs<XCOFF::SymbolAuxType>(
+ getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset));
+}
+
void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
uintptr_t TableAddress) const {
if (Addr < TableAddress)
@@ -115,14 +128,12 @@ XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
return viewAs<XCOFFSectionHeader64>(Ref.p);
}
-const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
- assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
+XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const {
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;
+ return XCOFFSymbolRef(Ref, this);
}
const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
@@ -148,15 +159,15 @@ XCOFFObjectFile::sectionHeaderTable64() const {
}
void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
- const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
- SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
+ uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress(
+ Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 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));
+ if (NextSymbolAddr != getEndOfSymbolTableAddress())
+ checkSymbolEntryPointer(NextSymbolAddr);
#endif
- Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
+ Symb.p = NextSymbolAddr;
}
Expected<StringRef>
@@ -178,34 +189,21 @@ XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
Expected<StringRef>
XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
- if (CFileEntPtr->NameInStrTbl.Magic !=
- XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
+ if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::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);
+ return toSymbolRef(Symb).getName();
}
Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
- assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
- return toSymbolEntry(Symb)->Value;
+ return toSymbolRef(Symb).getValue();
}
uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
- assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
- return toSymbolEntry(Symb)->Value;
+ return toSymbolRef(Symb).getValue();
}
uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
@@ -222,8 +220,7 @@ XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
Expected<section_iterator>
XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
- const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
- int16_t SectNum = SymEntPtr->SectionNumber;
+ const int16_t SectNum = toSymbolRef(Symb).getSectionNumber();
if (isReservedSectionNumber(SectNum))
return section_end();
@@ -376,7 +373,7 @@ symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
return symbol_end();
DataRefImpl SymDRI;
- SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index);
+ SymDRI.p = getSymbolEntryAddressByIndex(Index);
return symbol_iterator(SymbolRef(SymDRI, this));
}
@@ -402,19 +399,15 @@ Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
}
basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
- if (is64Bit())
- report_fatal_error("64-bit support not implemented yet");
DataRefImpl SymDRI;
SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
return basic_symbol_iterator(SymbolRef(SymDRI, this));
}
basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
- if (is64Bit())
- report_fatal_error("64-bit support not implemented yet");
DataRefImpl SymDRI;
- SymDRI.p = reinterpret_cast<uintptr_t>(
- SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32());
+ const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries();
+ SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries);
return basic_symbol_iterator(SymbolRef(SymDRI, this));
}
@@ -501,9 +494,8 @@ Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
}
Expected<StringRef>
-XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
- assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
- int16_t SectionNum = SymEntPtr->SectionNumber;
+XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const {
+ const int16_t SectionNum = SymEntPtr.getSectionNumber();
switch (SectionNum) {
case XCOFF::N_DEBUG:
@@ -564,10 +556,13 @@ uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
return fileHeader64()->NumberOfSymTableEntries;
}
+uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
+ return is64Bit() ? getNumberOfSymbolTableEntries64()
+ : getLogicalNumberOfSymbolTableEntries32();
+}
+
uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
- uint32_t NumberOfSymTableEntries =
- is64Bit() ? getNumberOfSymbolTableEntries64()
- : getLogicalNumberOfSymbolTableEntries32();
+ const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
}
@@ -593,16 +588,20 @@ uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
XCOFF::SymbolTableEntrySize;
}
+uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const {
+ return getAdvancedSymbolEntryAddress(
+ reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index);
+}
+
Expected<StringRef>
XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
- if (is64Bit())
- report_fatal_error("64-bit symbol table support not implemented yet.");
+ const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
- if (Index >= getLogicalNumberOfSymbolTableEntries32())
+ if (Index >= NumberOfSymTableEntries)
return errorCodeToError(object_error::invalid_symbol_index);
DataRefImpl SymDRI;
- SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index);
+ SymDRI.p = getSymbolEntryAddressByIndex(Index);
return getSymbolName(SymDRI);
}
@@ -745,20 +744,21 @@ XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
Obj->SectionHeaderTable = SecHeadersOrErr.get();
}
- // 64-bit object supports only file header and section headers for now.
- if (Obj->is64Bit())
- return std::move(Obj);
+ const uint32_t NumberOfSymbolTableEntries =
+ Obj->getNumberOfSymbolTableEntries();
// If there is no symbol table we are done parsing the memory buffer.
- if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0)
+ if (NumberOfSymbolTableEntries == 0)
return std::move(Obj);
// Parse symbol table.
- CurOffset = Obj->fileHeader32()->SymbolTableOffset;
- uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
- Obj->getLogicalNumberOfSymbolTableEntries32();
+ CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64()
+ : Obj->getSymbolTableOffset32();
+ const uint64_t SymbolTableSize =
+ static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) *
+ NumberOfSymbolTableEntries;
auto SymTableOrErr =
- getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize);
+ getObject<void *>(Data, Base + CurOffset, SymbolTableSize);
if (Error E = SymTableOrErr.takeError())
return std::move(E);
Obj->SymbolTblPtr = SymTableOrErr.get();
@@ -780,74 +780,103 @@ ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
return XCOFFObjectFile::create(FileType, MemBufRef);
}
-XCOFF::StorageClass XCOFFSymbolRef::getStorageClass() const {
- return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->StorageClass;
-}
+bool XCOFFSymbolRef::isFunction() const {
+ if (!isCsectSymbol())
+ return false;
-uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const {
- return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries;
-}
+ if (getSymbolType() & FunctionSym)
+ return true;
-// TODO: The function needs to return an error if there is no csect auxiliary
-// entry.
-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.");
+ Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef();
+ if (!ExpCsectAuxEnt)
+ return false;
- // In XCOFF32, the csect auxilliary entry is always the last auxiliary
- // entry for the symbol.
- uintptr_t AuxAddr = getWithOffset(
- SymEntDataRef.p, XCOFF::SymbolTableEntrySize * getNumberOfAuxEntries());
+ const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get();
-#ifndef NDEBUG
- OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
-#endif
+ // A function definition should be a label definition.
+ // FIXME: This is not necessarily the case when -ffunction-sections is
+ // enabled.
+ if (!CsectAuxRef.isLabel())
+ return false;
- return reinterpret_cast<const XCOFFCsectAuxEnt32 *>(AuxAddr);
-}
+ if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR)
+ return false;
-uint16_t XCOFFSymbolRef::getType() const {
- return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SymbolType;
-}
+ const int16_t SectNum = getSectionNumber();
+ Expected<DataRefImpl> SI = OwningObjectPtr->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;
+ }
-int16_t XCOFFSymbolRef::getSectionNumber() const {
- return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber;
+ return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
}
-// TODO: The function name needs to be changed to express the purpose of the
-// function.
-bool XCOFFSymbolRef::hasCsectAuxEnt() const {
+bool XCOFFSymbolRef::isCsectSymbol() 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.");
+Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
+ assert(isCsectSymbol() &&
+ "Calling csect symbol interface with a non-csect symbol.");
- if (getType() & FunctionSym)
- return true;
+ uint8_t NumberOfAuxEntries = getNumberOfAuxEntries();
- if (!hasCsectAuxEnt())
- return false;
+ Expected<StringRef> NameOrErr = getName();
+ if (auto Err = NameOrErr.takeError())
+ return std::move(Err);
- const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32();
+ if (!NumberOfAuxEntries) {
+ return createStringError(object_error::parse_failed,
+ "csect symbol \"" + *NameOrErr +
+ "\" contains no auxiliary entry");
+ }
- // A function definition should be a label definition.
- if ((CsectAuxEnt->SymbolAlignmentAndType & SymTypeMask) != XCOFF::XTY_LD)
- return false;
+ if (!OwningObjectPtr->is64Bit()) {
+ // In XCOFF32, the csect auxilliary entry is always the last auxiliary
+ // entry for the symbol.
+ uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+ getEntryAddress(), NumberOfAuxEntries);
+ return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr));
+ }
- if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR)
- return false;
+ // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type.
+ // We need to iterate through all the auxiliary entries to find it.
+ for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) {
+ uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+ getEntryAddress(), Index);
+ if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) ==
+ XCOFF::SymbolAuxType::AUX_CSECT) {
+#ifndef NDEBUG
+ OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
+#endif
+ return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr));
+ }
+ }
- int16_t SectNum = getSectionNumber();
- Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
- if (!SI)
- return false;
+ return createStringError(
+ object_error::parse_failed,
+ "a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\"");
+}
- return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
+Expected<StringRef> XCOFFSymbolRef::getName() const {
+ // A storage class value with the high-order bit on indicates that the name is
+ // a symbolic debugger stabstring.
+ if (getStorageClass() & 0x80)
+ return StringRef("Unimplemented Debug Name");
+
+ if (Entry32) {
+ if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
+ return generateXCOFFFixedNameStringRef(Entry32->SymbolName);
+
+ return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset);
+ }
+
+ return OwningObjectPtr->getStringTableEntry(Entry64->Offset);
}
// Explictly instantiate template classes.