diff options
Diffstat (limited to 'llvm/lib/Object/XCOFFObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/XCOFFObjectFile.cpp | 231 |
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. |