[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