[llvm] dcd5abd - [AIX] llvm-readobj support a new option --exception-section for xcoff object file.
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 19 07:56:38 PDT 2022
Author: zhijian
Date: 2022-09-19T10:55:48-04:00
New Revision: dcd5abd4c482d6d5301990078091f1d26dc17872
URL: https://github.com/llvm/llvm-project/commit/dcd5abd4c482d6d5301990078091f1d26dc17872
DIFF: https://github.com/llvm/llvm-project/commit/dcd5abd4c482d6d5301990078091f1d26dc17872.diff
LOG: [AIX] llvm-readobj support a new option --exception-section for xcoff object file.
Summary:
llvm-readobj support a new option --exception-section for xcoff object file.
https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format#XCOFF__iua3i23ajbau
Reviewers: James Henderson,Paul Scoropan
Differential Revision: https://reviews.llvm.org/D133030
Added:
llvm/test/tools/llvm-readobj/XCOFF/exception-section.test
llvm/test/tools/llvm-readobj/XCOFF/invalid-exception-section.test
Modified:
llvm/docs/CommandGuide/llvm-readobj.rst
llvm/include/llvm/Object/XCOFFObjectFile.h
llvm/lib/Object/XCOFFObjectFile.cpp
llvm/tools/llvm-readobj/ObjDumper.h
llvm/tools/llvm-readobj/Opts.td
llvm/tools/llvm-readobj/XCOFFDumper.cpp
llvm/tools/llvm-readobj/llvm-readobj.cpp
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst
index b33e72240346..859b49003bbb 100644
--- a/llvm/docs/CommandGuide/llvm-readobj.rst
+++ b/llvm/docs/CommandGuide/llvm-readobj.rst
@@ -330,6 +330,10 @@ The following options are implemented only for the XCOFF file format.
Display XCOFF Auxiliary header.
+.. option:: --exception-section
+
+ Display XCOFF exception section entries.
+
EXIT STATUS
-----------
diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h
index 68d9afff887c..30373a80de44 100644
--- a/llvm/include/llvm/Object/XCOFFObjectFile.h
+++ b/llvm/include/llvm/Object/XCOFFObjectFile.h
@@ -220,6 +220,35 @@ struct LoaderSectionHeader64 {
support::big32_t OffsetToRelEnt;
};
+template <typename AddressType> struct ExceptionSectionEntry {
+ union {
+ support::ubig32_t SymbolIdx;
+ AddressType TrapInstAddr;
+ };
+ uint8_t LangId;
+ uint8_t Reason;
+
+ uint32_t getSymbolIndex() const {
+ assert(Reason == 0 && "Get symbol table index of the function only when "
+ "the e_reason field is 0.");
+ return SymbolIdx;
+ }
+
+ uint64_t getTrapInstAddr() const {
+ assert(Reason != 0 && "Zero is not a valid trap exception reason code.");
+ return TrapInstAddr;
+ }
+ uint8_t getLangID() const { return LangId; }
+ uint8_t getReason() const { return Reason; }
+};
+
+typedef ExceptionSectionEntry<support::ubig32_t> ExceptionSectionEntry32;
+typedef ExceptionSectionEntry<support::ubig64_t> ExceptionSectionEntry64;
+
+// Explicit extern template declarations.
+extern template struct ExceptionSectionEntry<support::ubig32_t>;
+extern template struct ExceptionSectionEntry<support::ubig64_t>;
+
struct XCOFFStringTable {
uint32_t Size;
const char *Data;
@@ -464,6 +493,11 @@ class XCOFFObjectFile : public ObjectFile {
uintptr_t getEndOfSymbolTableAddress() const;
Expected<uintptr_t> getLoaderSectionAddress() const;
+ DataRefImpl getSectionByType(XCOFF::SectionTypeFlags SectType) const;
+ uint64_t getSectionFileOffsetToRawData(DataRefImpl Sec) const;
+ Expected<uintptr_t>
+ getSectionFileOffsetToRawData(XCOFF::SectionTypeFlags SectType) 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.
@@ -618,6 +652,10 @@ class XCOFFObjectFile : public ObjectFile {
// Loader section related interfaces.
Expected<StringRef> getImportFileTable() const;
+ // Exception-related interface.
+ template <typename ExceptEnt>
+ Expected<ArrayRef<ExceptEnt>> getExceptionEntries() const;
+
// This function returns string table entry.
Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index ff39fe1794c0..b1f44f1db667 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -86,6 +86,9 @@ uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const {
return (Info & XR_BIASED_LENGTH_MASK) + 1;
}
+template struct ExceptionSectionEntry<support::ubig32_t>;
+template struct ExceptionSectionEntry<support::ubig64_t>;
+
uintptr_t
XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
uint32_t Distance) {
@@ -392,6 +395,13 @@ uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
return Result;
}
+uint64_t XCOFFObjectFile::getSectionFileOffsetToRawData(DataRefImpl Sec) const {
+ if (is64Bit())
+ return toSection64(Sec)->FileOffsetToRawData;
+
+ return toSection32(Sec)->FileOffsetToRawData;
+}
+
Expected<uintptr_t> XCOFFObjectFile::getLoaderSectionAddress() const {
uint64_t OffsetToLoaderSection = 0;
uint64_t SizeOfLoaderSection = 0;
@@ -429,6 +439,53 @@ Expected<uintptr_t> XCOFFObjectFile::getLoaderSectionAddress() const {
return LoderSectionStart;
}
+Expected<uintptr_t> XCOFFObjectFile::getSectionFileOffsetToRawData(
+ XCOFF::SectionTypeFlags SectType) const {
+ DataRefImpl DRI = getSectionByType(SectType);
+
+ if (DRI.p == 0) // No section is not an error.
+ return 0;
+
+ uint64_t SectionOffset = getSectionFileOffsetToRawData(DRI);
+ uint64_t SizeOfSection = getSectionSize(DRI);
+
+ uintptr_t SectionStart = reinterpret_cast<uintptr_t>(base() + SectionOffset);
+ if (Error E = Binary::checkOffset(Data, SectionStart, SizeOfSection)) {
+ SmallString<32> UnknownType;
+ Twine(("<Unknown:") + Twine::utohexstr(SectType) + ">")
+ .toVector(UnknownType);
+ const char *SectionName = UnknownType.c_str();
+
+ switch (SectType) {
+#define ECASE(Value, String) \
+ case XCOFF::Value: \
+ SectionName = String; \
+ break
+
+ ECASE(STYP_PAD, "pad");
+ ECASE(STYP_DWARF, "dwarf");
+ ECASE(STYP_TEXT, "text");
+ ECASE(STYP_DATA, "data");
+ ECASE(STYP_BSS, "bss");
+ ECASE(STYP_EXCEPT, "expect");
+ ECASE(STYP_INFO, "info");
+ ECASE(STYP_TDATA, "tdata");
+ ECASE(STYP_TBSS, "tbss");
+ ECASE(STYP_LOADER, "loader");
+ ECASE(STYP_DEBUG, "debug");
+ ECASE(STYP_TYPCHK, "typchk");
+ ECASE(STYP_OVRFLO, "ovrflo");
+#undef ECASE
+ }
+ return createError(toString(std::move(E)) + ": " + SectionName +
+ " section with offset 0x" +
+ Twine::utohexstr(SectionOffset) + " and size 0x" +
+ Twine::utohexstr(SizeOfSection) +
+ " goes past the end of the file");
+ }
+ return SectionStart;
+}
+
bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
return false;
}
@@ -738,6 +795,22 @@ Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
return DRI;
}
+DataRefImpl
+XCOFFObjectFile::getSectionByType(XCOFF::SectionTypeFlags SectType) const {
+ DataRefImpl DRI;
+ auto GetSectionAddr = [&](const auto &Sections) {
+ for (const auto &Sec : Sections)
+ if (Sec.getSectionType() == SectType)
+ return reinterpret_cast<uintptr_t>(&Sec);
+ return 0ul;
+ };
+ if (is64Bit())
+ DRI.p = GetSectionAddr(sections64());
+ else
+ DRI.p = GetSectionAddr(sections32());
+ return DRI;
+}
+
Expected<StringRef>
XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const {
const int16_t SectionNum = SymEntPtr.getSectionNumber();
@@ -960,6 +1033,31 @@ Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const {
return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries);
}
+template <typename ExceptEnt>
+Expected<ArrayRef<ExceptEnt>> XCOFFObjectFile::getExceptionEntries() const {
+ assert(is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64) ||
+ !is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32));
+
+ Expected<uintptr_t> ExceptionSectOrErr =
+ getSectionFileOffsetToRawData(XCOFF::STYP_EXCEPT);
+ if (!ExceptionSectOrErr)
+ return ExceptionSectOrErr.takeError();
+
+ DataRefImpl DRI = getSectionByType(XCOFF::STYP_EXCEPT);
+ if (DRI.p == 0)
+ return ArrayRef<ExceptEnt>();
+
+ ExceptEnt *ExceptEntStart =
+ reinterpret_cast<ExceptEnt *>(*ExceptionSectOrErr);
+ return ArrayRef<ExceptEnt>(
+ ExceptEntStart, ExceptEntStart + getSectionSize(DRI) / sizeof(ExceptEnt));
+}
+
+template Expected<ArrayRef<ExceptionSectionEntry32>>
+XCOFFObjectFile::getExceptionEntries() const;
+template Expected<ArrayRef<ExceptionSectionEntry64>>
+XCOFFObjectFile::getExceptionEntries() const;
+
Expected<XCOFFStringTable>
XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
// If there is a string table, then the buffer must contain at least 4 bytes
diff --git a/llvm/test/tools/llvm-readobj/XCOFF/exception-section.test b/llvm/test/tools/llvm-readobj/XCOFF/exception-section.test
new file mode 100644
index 000000000000..03eb7e3a63aa
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/XCOFF/exception-section.test
@@ -0,0 +1,55 @@
+## Test the --exception-section option.
+
+# RUN: yaml2obj --docnum=1 %s -o %t_xcoff32.o
+# RUN: yaml2obj --docnum=2 %s -o %t_xcoff64.o
+# RUN: llvm-readobj --exception-section %t_xcoff32.o |\
+# RUN: FileCheck %s --check-prefixes=CHECK
+# RUN: llvm-readobj --exception-section %t_xcoff64.o |\
+# RUN: FileCheck %s --check-prefixes=CHECK
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1DF
+Sections:
+ - Name: .text
+ Flags: [ STYP_TEXT ]
+ - Name: .except
+ Flags: [ STYP_EXCEPT ]
+ SectionData: "000000000000000000340003"
+## ^------- -SymbolIndex=0
+## ^- -LangID=0
+## ^- -Reason=0
+## ^------- -Trap Instr Addr=0x34
+## ^- -LangID=0
+## ^- -Reason=3
+Symbols:
+ - Name: .bar
+ Section: .text
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1F7
+Sections:
+ - Name: .text
+ Flags: [ STYP_TEXT ]
+ - Name: .except
+ Flags: [ STYP_EXCEPT ]
+ SectionData: "0000000000000000000000000000000000340003"
+## ^--------------- -SymbolIndex=0
+## ^- -LangID=0
+## ^- -Reason=0
+## ^-------------- -Trap Instr Addr=0x34
+## ^- -LangID=0
+## ^- -Reason=3
+Symbols:
+ - Name: .bar
+ Section: .text
+
+# CHECK: Exception section {
+# CHECK-NEXT: Symbol: .bar (0)
+# CHECK-NEXT: LangID: 0
+# CHECK-NEXT: Reason: 0
+# CHECK-NEXT: Trap Instr Addr: 0x34
+# CHECK-NEXT: LangID: 0
+# CHECK-NEXT: Reason: 3
+# CHECK-NEXT: }
diff --git a/llvm/test/tools/llvm-readobj/XCOFF/invalid-exception-section.test b/llvm/test/tools/llvm-readobj/XCOFF/invalid-exception-section.test
new file mode 100644
index 000000000000..5a300fdb5c33
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/XCOFF/invalid-exception-section.test
@@ -0,0 +1,38 @@
+## Test decoding an invalid exception section and symbol index.
+
+# RUN: yaml2obj --docnum=1 %s -o %t_invalid_size.o
+# RUN: yaml2obj --docnum=2 %s -o %t_invalid_sym.o
+# RUN: llvm-readobj --exception-section %t_invalid_size.o 2>&1 |\
+# RUN: FileCheck -DFILE=%t_invalid_size.o %s --check-prefixes=CHECK-WARN-SIZE
+# RUN: llvm-readobj --exception-section %t_invalid_sym.o 2>&1 |\
+# RUN: FileCheck -DFILE=%t_invalid_sym.o %s --check-prefixes=CHECK-WARN-SYM
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1DF
+Sections:
+ - Name: .text
+ Flags: [ STYP_TEXT ]
+ - Name: .except
+ Size: 1000
+ Flags: [ STYP_EXCEPT ]
+ SectionData: "000000000000"
+Symbols:
+ - Name: .bar
+ Section: .text
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1F7
+Sections:
+ - Name: .text
+ Flags: [ STYP_TEXT ]
+ - Name: .except
+ Flags: [ STYP_EXCEPT ]
+ SectionData: "00000004000000000000"
+Symbols:
+ - Name: .bar
+ Section: .text
+
+# CHECK-WARN-SIZE: warning: '[[FILE]]': The end of the file was unexpectedly encountered: expect section with offset 0x64 and size 0x3e8 goes past the end of the file
+# CHECK-WARN-SYM: warning: '[[FILE]]': symbol index 4 exceeds symbol count 1
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index 292efd2ae350..f1cbdcf0ca05 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -157,6 +157,7 @@ class ObjDumper {
// Only implement for XCOFF
virtual void printAuxiliaryHeader() {}
+ virtual void printExceptionSection() {}
// Only implemented for MachO.
virtual void printMachODataInCode() { }
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index 4687fc71245f..eee8c685eb50 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -88,6 +88,7 @@ def coff_tls_directory : FF<"coff-tls-directory", "Display TLS directory">, Grou
// XCOFF specific options.
def grp_xcoff : OptionGroup<"kind">, HelpText<"OPTIONS (XCOFF specific)">;
def auxiliary_header : FF<"auxiliary-header" , "Display the auxiliary header">, Group<grp_xcoff>;
+def exception_section : FF<"exception-section" , "Display the exception section entries">, Group<grp_xcoff>;
def help : FF<"help", "Display this help">;
def version : FF<"version", "Display the version">;
diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp
index ccae66f20127..b2a647543814 100644
--- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp
@@ -39,6 +39,7 @@ class XCOFFDumper : public ObjDumper {
void printStackMap() const override;
void printNeededLibraries() override;
void printStringTable() override;
+ void printExceptionSection() override;
ScopedPrinter &getScopedPrinter() const { return W; }
@@ -46,6 +47,9 @@ class XCOFFDumper : public ObjDumper {
template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
template <typename T> void printGenericSectionHeader(T &Sec) const;
template <typename T> void printOverflowSectionHeader(T &Sec) const;
+ template <typename T>
+ void printExceptionSectionEntry(const T &ExceptionSectEnt) const;
+ template <typename T> void printExceptionSectionEntries() const;
template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress);
void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);
@@ -129,6 +133,47 @@ void XCOFFDumper::printSectionHeaders() {
printSectionHeaders(Obj.sections32());
}
+template <typename T>
+void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const {
+ if (ExceptionSectEnt.getReason())
+ W.printHex("Trap Instr Addr", ExceptionSectEnt.getTrapInstAddr());
+ else {
+ uint32_t SymIdx = ExceptionSectEnt.getSymbolIndex();
+ Expected<StringRef> ErrOrSymbolName = Obj.getSymbolNameByIndex(SymIdx);
+ if (Error E = ErrOrSymbolName.takeError()) {
+ reportUniqueWarning(std::move(E));
+ return;
+ }
+ StringRef SymName = *ErrOrSymbolName;
+
+ W.printNumber("Symbol", SymName, SymIdx);
+ }
+ W.printNumber("LangID", ExceptionSectEnt.getLangID());
+ W.printNumber("Reason", ExceptionSectEnt.getReason());
+}
+
+template <typename T> void XCOFFDumper::printExceptionSectionEntries() const {
+ Expected<ArrayRef<T>> ExceptSectEntsOrErr = Obj.getExceptionEntries<T>();
+ if (Error E = ExceptSectEntsOrErr.takeError()) {
+ reportUniqueWarning(std::move(E));
+ return;
+ }
+ ArrayRef<T> ExceptSectEnts = *ExceptSectEntsOrErr;
+
+ DictScope DS(W, "Exception section");
+ if (ExceptSectEnts.empty())
+ return;
+ for (auto &Ent : ExceptSectEnts)
+ printExceptionSectionEntry(Ent);
+}
+
+void XCOFFDumper::printExceptionSection() {
+ if (Obj.is64Bit())
+ printExceptionSectionEntries<ExceptionSectionEntry64>();
+ else
+ printExceptionSectionEntries<ExceptionSectionEntry32>();
+}
+
void XCOFFDumper::printRelocations() {
if (Obj.is64Bit())
printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64());
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index e1ebbeb41f28..06c6f7c4bff7 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -162,6 +162,7 @@ static bool COFFTLSDirectory;
// XCOFF specific options.
static bool XCOFFAuxiliaryHeader;
+static bool XCOFFExceptionSection;
OutputStyleTy Output = OutputStyleTy::LLVM;
static std::vector<std::string> InputFilenames;
@@ -302,6 +303,7 @@ static void parseOptions(const opt::InputArgList &Args) {
// XCOFF specific options.
opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header);
+ opts::XCOFFExceptionSection = Args.hasArg(OPT_exception_section);
opts::InputFilenames = Args.getAllArgValues(OPT_INPUT);
}
@@ -395,6 +397,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
if (opts::FileHeaders)
Dumper->printFileHeaders();
+ // Auxiliary header in XOCFF is right after the file header, so print the data
+ // here.
if (Obj.isXCOFF() && opts::XCOFFAuxiliaryHeader)
Dumper->printAuxiliaryHeader();
@@ -502,6 +506,10 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
if (opts::CGProfile)
Dumper->printCGProfile();
}
+
+ if (Obj.isXCOFF() && opts::XCOFFExceptionSection)
+ Dumper->printExceptionSection();
+
if (opts::PrintStackMap)
Dumper->printStackMap();
if (opts::PrintStackSizes)
More information about the llvm-commits
mailing list