[llvm] 29b0a25 - [llvm-objdump] Print out xcoff file header for xcoff object file with option private-headers (#96350)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 15 10:50:58 PDT 2024


Author: zhijian lin
Date: 2024-08-15T13:50:54-04:00
New Revision: 29b0a251c14b248848f2bbad1618b66a0c173336

URL: https://github.com/llvm/llvm-project/commit/29b0a251c14b248848f2bbad1618b66a0c173336
DIFF: https://github.com/llvm/llvm-project/commit/29b0a251c14b248848f2bbad1618b66a0c173336.diff

LOG: [llvm-objdump] Print out  xcoff file header for xcoff object file with option private-headers (#96350)

Print out the XCOFF file header and load section header for the XCOFF
object file using llvm-objdump with the --private-headers option.

Added: 
    llvm/test/tools/llvm-objdump/XCOFF/private-headers.test

Modified: 
    llvm/tools/llvm-objdump/XCOFFDump.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-objdump/XCOFF/private-headers.test b/llvm/test/tools/llvm-objdump/XCOFF/private-headers.test
new file mode 100644
index 00000000000000..9f1e60705bedf3
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/XCOFF/private-headers.test
@@ -0,0 +1,52 @@
+## Test the --private-headers option for XCOFF object files.
+
+# RUN: yaml2obj -DMAGIC=0x1DF --docnum=1 %s -o %t_xcoff32.o
+# RUN: yaml2obj -DMAGIC=0x1F7 --docnum=1 %s -o %t_xcoff64.o
+# RUN: llvm-objdump --private-headers %t_xcoff32.o | \
+# RUN:   FileCheck %s --check-prefixes=CHECK32 --match-full-lines --strict-whitespace
+# RUN: llvm-objdump --private-headers %t_xcoff64.o | \
+# RUN:   FileCheck %s --check-prefixes=CHECK64 --match-full-lines --strict-whitespace
+
+--- !XCOFF
+FileHeader:
+  MagicNumber:       [[MAGIC]]
+  CreationTime:      1234
+Sections:
+  - Name:            .text
+    Flags:           [ STYP_TEXT ]
+    SectionData:     "9061FFF880820000"
+  - Name:            .data
+    Flags:           [ STYP_DATA ]
+    SectionData:     "0000000000000FC0"
+
+#      CHECK32:---File Header:
+# CHECK32-NEXT:Magic:              0x1df
+# CHECK32-NEXT:NumberOfSections:   2
+# CHECK32-NEXT:Timestamp:          1970-01-01 00:20:34 (1234)
+# CHECK32-NEXT:SymbolTableOffset:  0x0
+# CHECK32-NEXT:SymbolTableEntries: 0
+# CHECK32-NEXT:OptionalHeaderSize: 0x0
+# CHECK32-NEXT:Flags:              0x0
+
+#      CHECK64:---File Header:
+# CHECK64-NEXT:Magic:              0x1f7
+# CHECK64-NEXT:NumberOfSections:   2
+# CHECK64-NEXT:Timestamp:          1970-01-01 00:20:34 (1234)
+# CHECK64-NEXT:SymbolTableOffset:  0x0
+# CHECK64-NEXT:SymbolTableEntries: 0
+# CHECK64-NEXT:OptionalHeaderSize: 0x0
+# CHECK64-NEXT:Flags:              0x0
+
+## Test if the creation time of XCOFF is zero and the number of symbols is negative.
+# RUN: yaml2obj -DMAGIC=0x1DF --docnum=2 %s -o %t_xcoff_timestamp.o
+# RUN: llvm-objdump --private-headers %t_xcoff_timestamp.o | \
+# RUN:   FileCheck %s --match-full-lines
+
+--- !XCOFF
+FileHeader:
+  MagicNumber:          0x1DF
+  CreationTime:         0
+  EntriesInSymbolTable: -1
+
+# CHECK: Timestamp:          None (0)
+# CHECK: SymbolTableEntries: Reserved Value (-1)

diff  --git a/llvm/tools/llvm-objdump/XCOFFDump.cpp b/llvm/tools/llvm-objdump/XCOFFDump.cpp
index d9c00c09620983..5617313cdbf721 100644
--- a/llvm/tools/llvm-objdump/XCOFFDump.cpp
+++ b/llvm/tools/llvm-objdump/XCOFFDump.cpp
@@ -20,7 +20,9 @@
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Endian.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 
 using namespace llvm;
@@ -30,10 +32,86 @@ using namespace llvm::support;
 
 namespace {
 class XCOFFDumper : public objdump::Dumper {
+  const XCOFFObjectFile &Obj;
+  unsigned Width;
+
 public:
-  XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O) {}
-  void printPrivateHeaders() override {}
+  XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O), Obj(O) {}
+
+private:
+  void printPrivateHeaders() override;
+  void printFileHeader();
+  FormattedString formatName(StringRef Name);
+  void printHex(StringRef Name, uint64_t Value);
+  void printNumber(StringRef Name, uint64_t Value);
+  void printStrHex(StringRef Name, StringRef Str, uint64_t Value);
+  void setWidth(unsigned W) { Width = W; };
 };
+
+void XCOFFDumper::printPrivateHeaders() { printFileHeader(); }
+
+FormattedString XCOFFDumper::formatName(StringRef Name) {
+  return FormattedString(Name, Width, FormattedString::JustifyLeft);
+}
+
+void XCOFFDumper::printHex(StringRef Name, uint64_t Value) {
+  outs() << formatName(Name) << format_hex(Value, 0) << "\n";
+}
+
+void XCOFFDumper::printNumber(StringRef Name, uint64_t Value) {
+  outs() << formatName(Name) << format_decimal(Value, 0) << "\n";
+}
+
+void XCOFFDumper::printStrHex(StringRef Name, StringRef Str, uint64_t Value) {
+  outs() << formatName(Name) << Str << " (" << format_decimal(Value, 0)
+         << ")\n";
+}
+
+void XCOFFDumper::printFileHeader() {
+  setWidth(20);
+  outs() << "\n---File Header:\n";
+  printHex("Magic:", Obj.getMagic());
+  printNumber("NumberOfSections:", Obj.getNumberOfSections());
+
+  int32_t Timestamp = Obj.getTimeStamp();
+  if (Timestamp > 0) {
+    // This handling of the timestamp assumes that the host system's time_t is
+    // compatible with AIX time_t. If a platform is not compatible, the lit
+    // tests will let us know.
+    time_t TimeDate = Timestamp;
+
+    char FormattedTime[20] = {};
+
+    size_t BytesFormatted = std::strftime(FormattedTime, sizeof(FormattedTime),
+                                          "%F %T", std::gmtime(&TimeDate));
+    assert(BytesFormatted && "The size of the buffer FormattedTime is less "
+                             "than the size of the date/time string.");
+    printStrHex("Timestamp:", FormattedTime, Timestamp);
+  } else {
+    // Negative timestamp values are reserved for future use.
+    printStrHex("Timestamp:", Timestamp == 0 ? "None" : "Reserved Value",
+                Timestamp);
+  }
+
+  // The number of symbol table entries is an unsigned value in 64-bit objects
+  // and a signed value (with negative values being 'reserved') in 32-bit
+  // objects.
+  if (Obj.is64Bit()) {
+    printHex("SymbolTableOffset:", Obj.getSymbolTableOffset64());
+    printNumber("SymbolTableEntries:", Obj.getNumberOfSymbolTableEntries64());
+  } else {
+    printHex("SymbolTableOffset:", Obj.getSymbolTableOffset32());
+    int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
+    if (SymTabEntries >= 0)
+      printNumber("SymbolTableEntries:", SymTabEntries);
+    else
+      printStrHex("SymbolTableEntries:", "Reserved Value", SymTabEntries);
+  }
+
+  printHex("OptionalHeaderSize:", Obj.getOptionalHeaderSize());
+  printHex("Flags:", Obj.getFlags());
+}
+
 } // namespace
 
 std::unique_ptr<objdump::Dumper>


        


More information about the llvm-commits mailing list