summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Object/XCOFFObjectFile.cpp
diff options
context:
space:
mode:
authorJason Liu <jasonliu.development@gmail.com>2019-08-27 18:54:46 +0000
committerJason Liu <jasonliu.development@gmail.com>2019-08-27 18:54:46 +0000
commit7c72e82b2558228f53433b2b579e08d38405285a (patch)
treee59968d0138bd481a81951b36bbd459e2b430ff8 /llvm/lib/Object/XCOFFObjectFile.cpp
parent559ae14c9b6cf203e0e7495892080e52e89c1ea0 (diff)
downloadbcm5719-llvm-7c72e82b2558228f53433b2b579e08d38405285a.tar.gz
bcm5719-llvm-7c72e82b2558228f53433b2b579e08d38405285a.zip
[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
Diffstat (limited to 'llvm/lib/Object/XCOFFObjectFile.cpp')
-rw-r--r--llvm/lib/Object/XCOFFObjectFile.cpp163
1 files changed, 143 insertions, 20 deletions
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index 7e3e8f96a41..7bd0dd68b91 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -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
OpenPOWER on IntegriCloud