[llvm] [SystemZ][z/OS] Add goffdumper/llvm-readobj tools (PR #71071)

Yusra Syeda via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 2 08:58:43 PDT 2023


https://github.com/ysyeda created https://github.com/llvm/llvm-project/pull/71071

This PR adds the GOFFDumper. It contains a test which uses llvm-readobj to check the symbols of the provided GOFF object file.

>From cb093ff5e7c994c5e638d8858c1afb58115581bf Mon Sep 17 00:00:00 2001
From: Yusra Syeda <yusra.syeda at ibm.com>
Date: Thu, 2 Nov 2023 11:55:43 -0400
Subject: [PATCH] add goffdumper and test

---
 llvm/lib/Object/GOFFObjectFile.cpp            |   9 ++
 llvm/lib/Object/ObjectFile.cpp                |   3 +-
 .../llvm-readobj/GOFF/Inputs/goff-basics.o    | Bin 0 -> 3120 bytes
 .../tools/llvm-readobj/GOFF/goff-basics.test  |  69 +++++++++++++
 llvm/tools/llvm-readobj/CMakeLists.txt        |   1 +
 llvm/tools/llvm-readobj/GOFFDumper.cpp        |  94 ++++++++++++++++++
 llvm/tools/llvm-readobj/ObjDumper.h           |   4 +
 llvm/tools/llvm-readobj/llvm-readobj.cpp      |   4 +
 8 files changed, 183 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/tools/llvm-readobj/GOFF/Inputs/goff-basics.o
 create mode 100644 llvm/test/tools/llvm-readobj/GOFF/goff-basics.test
 create mode 100644 llvm/tools/llvm-readobj/GOFFDumper.cpp

diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp
index 76a13559ebfe352..03f86f303668457 100644
--- a/llvm/lib/Object/GOFFObjectFile.cpp
+++ b/llvm/lib/Object/GOFFObjectFile.cpp
@@ -168,6 +168,15 @@ GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err)
       LLVM_DEBUG(dbgs() << "  --  ESD " << EsdId << "\n");
       break;
     }
+    case GOFF::RT_TXT:
+      LLVM_DEBUG(dbgs() << "  --  TXT (GOFF record type) unhandled\n");
+      break;
+    case GOFF::RT_RLD:
+      LLVM_DEBUG(dbgs() << "  --  RLD (GOFF record type) unhandled\n");
+      break;
+    case GOFF::RT_LEN:
+      LLVM_DEBUG(dbgs() << "  --  LEN (GOFF record type) unhandled\n");
+      break;
     case GOFF::RT_END:
       LLVM_DEBUG(dbgs() << "  --  END (GOFF record type) unhandled\n");
       break;
diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp
index 428166f58070d0b..16c6003db4810ac 100644
--- a/llvm/lib/Object/ObjectFile.cpp
+++ b/llvm/lib/Object/ObjectFile.cpp
@@ -154,7 +154,6 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
   case file_magic::windows_resource:
   case file_magic::pdb:
   case file_magic::minidump:
-  case file_magic::goff_object:
   case file_magic::cuda_fatbinary:
   case file_magic::offload_binary:
   case file_magic::dxcontainer_object:
@@ -182,6 +181,8 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
   case file_magic::macho_kext_bundle:
   case file_magic::macho_file_set:
     return createMachOObjectFile(Object);
+  case file_magic::goff_object:
+    return createGOFFObjectFile(Object);
   case file_magic::coff_object:
   case file_magic::coff_import_library:
   case file_magic::pecoff_executable:
diff --git a/llvm/test/tools/llvm-readobj/GOFF/Inputs/goff-basics.o b/llvm/test/tools/llvm-readobj/GOFF/Inputs/goff-basics.o
new file mode 100644
index 0000000000000000000000000000000000000000..4988c29ef3dc2f2eaf301c58ceec53e47b756df1
GIT binary patch
literal 3120
zcmb_eJ8u&~5T3m~k_!+pNsuT|Fo7T74$A8&kWdOlL4jP-SfZdKg&j~3e}MEUC at 53V
zJ7*U(G?DV?B3nYDyK`boRN<Swxp?o+KF1DYt#9Y`?S8X!4;|99qKXo9>@AEb$gfhI
zx%m0()>d`1v7;UO@^R-wP>?f~OOsi_K~mu!bt4b!x=NAnvSU7|{q8geX9T{0G=nj1
zxo0aJlocSUl6uVMEZ<Hxc2-^Z@}{$VPi#z8x3zfgx^z9JMqW at 04qENO8Tc~KYZ#^w
z`K;I?i=}8I!68-VfGppDjsHWiKVEtcBg;1huj?t*C^+8*;kyvjHa3n951Z(}UOsYm
z3kt$DnaAKg+Tz)YF56l>NBz(*rlfPv*SEJD*qPCYQn~rei5At65a4m$P={j7G4;#e
zAMqB^M+Q??F_%>T2oKxO4W>$ZjcxY+Siix4R}i%+$-?(0)I!WD`7Q#FF>RTOueCqM
zxMc&)Fjt=>N%-ELggGVO67U$)mQ+uUKi@~3lilAPw%K5qn?^`%qn}qLkLqTnxxL!Y
z*73e+KCb%`MiwuDGS^W~Bs%hx^MdyNQKx&{1-gTTWsKxJnR`wIFGbtn=`zQvrep}-
z3e*IzBCgbB65d`K at 2-Wno&pkO5?(98<C7TfO{{c60k!dqV0eS!b<K+13W~AvEPUr!
z{@3F7$n942GK~m%B_Snp-@?xT&M(-AUe at c>Ff*bum+k!gd`Emw;RBxK-edPSao at L6
zS4p+l_g&MPi|Y%4H1B8z=!L!0C<-IJMA6?~KMKQMh(8IN{i4AZGM_<6?v34yeWEIO
z{5-YAh4REUTy`#a{JgS- at n#aii&+m5623#rC1-+{x{r{W`nI|xlnDc#!X)nMVd5HI
zq^tcwKm2ph at qM2UpF83->_>gm4dYrtKLp5o1`>*VGG at 2_(8ksEES;-^kvv>3zNUUu
j$-M5Q`uxyJVEKc~G*K04vXt?2Oo3?s!ujB0c7 at 45*(AId

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/llvm-readobj/GOFF/goff-basics.test b/llvm/test/tools/llvm-readobj/GOFF/goff-basics.test
new file mode 100644
index 000000000000000..812cadd3c9b2654
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/GOFF/goff-basics.test
@@ -0,0 +1,69 @@
+# RUN: llvm-readobj --symbols %p/Inputs/goff-basics.o | \
+# RUN: FileCheck --check-prefix=SYMBOLSEXP %s
+
+# SYMBOLSEXP: File: {{.*}}goff-basics.o
+# SYMBOLSEXP-NEXT: Format: GOFF-SystemZ
+# SYMBOLSEXP-NEXT: Arch: s390x
+# SYMBOLSEXP-NEXT: AddressSize: 64bit
+# SYMBOLSEXP-NEXT: Symbols [
+# SYMBOLSEXP-NEXT:   Symbol {
+# SYMBOLSEXP-NEXT:     Name: goff-basics#S
+# SYMBOLSEXP-NEXT:     Value: 0
+# SYMBOLSEXP-NEXT:     Alignment: 0
+# SYMBOLSEXP-NEXT:   }
+# SYMBOLSEXP-NEXT:   Symbol {
+# SYMBOLSEXP-NEXT:     Name: goff-basics#C
+# SYMBOLSEXP-NEXT:     Value: 0
+# SYMBOLSEXP-NEXT:     Alignment: 0
+# SYMBOLSEXP-NEXT:   }
+# SYMBOLSEXP-NEXT:   Symbol {
+# SYMBOLSEXP-NEXT:     Name: .&ppa2
+# SYMBOLSEXP-NEXT:     Value: 0
+# SYMBOLSEXP-NEXT:     Alignment: 0
+# SYMBOLSEXP-NEXT:   }
+# SYMBOLSEXP-NEXT:   Symbol {
+# SYMBOLSEXP-NEXT:     Name: a
+# SYMBOLSEXP-NEXT:     Value: 0
+# SYMBOLSEXP-NEXT:     Alignment: 0
+# SYMBOLSEXP-NEXT:   }
+# SYMBOLSEXP-NEXT:   Symbol {
+# SYMBOLSEXP-NEXT:     Name: b
+# SYMBOLSEXP-NEXT:     Value: 0
+# SYMBOLSEXP-NEXT:     Alignment: 0
+# SYMBOLSEXP-NEXT:   }
+# SYMBOLSEXP-NEXT:   Symbol {
+# SYMBOLSEXP-NEXT:     Name: d
+# SYMBOLSEXP-NEXT:     Value: 0
+# SYMBOLSEXP-NEXT:     Alignment: 0
+# SYMBOLSEXP-NEXT:   }
+# SYMBOLSEXP-NEXT:   Symbol {
+# SYMBOLSEXP-NEXT:     Name: CELQSTRT
+# SYMBOLSEXP-NEXT:     Value: 0
+# SYMBOLSEXP-NEXT:     Alignment: 0
+# SYMBOLSEXP-NEXT:   }
+# SYMBOLSEXP-NEXT:   Symbol {
+# SYMBOLSEXP-NEXT:     Name: A
+# SYMBOLSEXP-NEXT:     Value: 16
+# SYMBOLSEXP-NEXT:     Alignment: 0
+# SYMBOLSEXP-NEXT:   }
+# SYMBOLSEXP-NEXT:   Symbol {
+# SYMBOLSEXP-NEXT:     Name: B
+# SYMBOLSEXP-NEXT:     Value: 48
+# SYMBOLSEXP-NEXT:     Alignment: 0
+# SYMBOLSEXP-NEXT:   }
+# SYMBOLSEXP-NEXT:   Symbol {
+# SYMBOLSEXP-NEXT:     Name: D
+# SYMBOLSEXP-NEXT:     Value: 80
+# SYMBOLSEXP-NEXT:     Alignment: 0
+# SYMBOLSEXP-NEXT:   }
+# SYMBOLSEXP-NEXT: ]
+
+
+# goff-basics.o was compiled with `clang -c goff-basics.c`
+# from the following source:
+# int a = 55;
+# int b;
+# double d;
+# int A() { return a; }
+# int B() { return b; }
+# double D() { return d; }
diff --git a/llvm/tools/llvm-readobj/CMakeLists.txt b/llvm/tools/llvm-readobj/CMakeLists.txt
index 0051f87b3c1039f..90637084ae7afa2 100644
--- a/llvm/tools/llvm-readobj/CMakeLists.txt
+++ b/llvm/tools/llvm-readobj/CMakeLists.txt
@@ -18,6 +18,7 @@ add_llvm_tool(llvm-readobj
   COFFDumper.cpp
   COFFImportDumper.cpp
   ELFDumper.cpp
+  GOFFDumper.cpp
   llvm-readobj.cpp
   MachODumper.cpp
   ObjDumper.cpp
diff --git a/llvm/tools/llvm-readobj/GOFFDumper.cpp b/llvm/tools/llvm-readobj/GOFFDumper.cpp
new file mode 100644
index 000000000000000..3cd3fd3866348e2
--- /dev/null
+++ b/llvm/tools/llvm-readobj/GOFFDumper.cpp
@@ -0,0 +1,94 @@
+#include "ObjDumper.h"
+#include "llvm-readobj.h"
+#include "llvm/Object/GOFFObjectFile.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+namespace {
+
+class GOFFDumper : public ObjDumper {
+public:
+  GOFFDumper(const GOFFObjectFile *Obj, ScopedPrinter &Writer)
+      : ObjDumper(Writer, Obj->getFileName()), Obj(Obj) {}
+
+  void printFileHeaders() override {}
+  void printSectionHeaders() override;
+  void printRelocations() override;
+  void printSymbols(bool ExtraSymInfo) override;
+  void printDynamicSymbols() override;
+  void printUnwindInfo() override {}
+  void printStackMap() const override {}
+
+  const object::GOFFObjectFile *getGOFFObject() const { return Obj; };
+
+private:
+  void printSymbol(const SymbolRef &Sym);
+
+  const GOFFObjectFile *Obj;
+};
+
+} // End anonymous namespace
+
+namespace llvm {
+std::unique_ptr<ObjDumper> createGOFFDumper(const object::GOFFObjectFile &Obj,
+                                            ScopedPrinter &Writer) {
+  return std::make_unique<GOFFDumper>(&Obj, Writer);
+}
+
+} // namespace llvm
+
+void GOFFDumper::printSymbol(const SymbolRef &Symbol) {
+  DictScope D(W, "Symbol");
+
+  Expected<StringRef> SymbolNameOrErr = Obj->getSymbolName(Symbol);
+  if (!SymbolNameOrErr)
+    reportError(SymbolNameOrErr.takeError(), Obj->getFileName());
+  W.printString("Name", SymbolNameOrErr.get());
+  Expected<uint64_t> SymVal = Symbol.getValue();
+  if (!SymVal)
+    reportError(SymVal.takeError(), Obj->getFileName());
+  W.printNumber("Value", *SymVal);
+  W.printNumber("Alignment", Symbol.getAlignment());
+}
+
+void GOFFDumper::printSectionHeaders() {
+  ListScope SectionsD(W, "Sections");
+  for (const SectionRef &Sec : Obj->sections()) {
+    StringRef Name = unwrapOrError(Obj->getFileName(), Sec.getName());
+
+    DictScope D(W, "Section");
+    W.printNumber("Index", Sec.getIndex());
+    W.printString("Name", Name);
+    W.printHex("Address", Sec.getAddress());
+    W.printHex("Size", Sec.getSize());
+    W.printNumber("Alignment", Sec.getAlignment().value());
+
+    if (opts::SectionSymbols) {
+      ListScope D(W, "Symbols");
+      for (const SymbolRef &Symbol : Obj->symbols()) {
+        if (!Sec.containsSymbol(Symbol))
+          continue;
+
+        printSymbol(Symbol);
+      }
+    }
+
+    if (opts::SectionData) {
+      StringRef Data = unwrapOrError(Obj->getFileName(), Sec.getContents());
+      W.printBinaryBlock("SectionData", Data);
+    }
+  }
+}
+
+void GOFFDumper::printSymbols(bool) {
+  ListScope Group(W, "Symbols");
+
+  for (const SymbolRef &Symbol : Obj->symbols())
+    printSymbol(Symbol);
+}
+
+void GOFFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); }
+
+void GOFFDumper::printRelocations() {}
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index 1d679453581bc84..a457e3bab331518 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -25,6 +25,7 @@ namespace object {
 class Archive;
 class COFFImportFile;
 class ObjectFile;
+class GOFFObjectFile;
 class XCOFFObjectFile;
 class ELFObjectFileBase;
 } // namespace object
@@ -206,6 +207,9 @@ std::unique_ptr<ObjDumper> createELFDumper(const object::ELFObjectFileBase &Obj,
 std::unique_ptr<ObjDumper> createMachODumper(const object::MachOObjectFile &Obj,
                                              ScopedPrinter &Writer);
 
+std::unique_ptr<ObjDumper> createGOFFDumper(const object::GOFFObjectFile &Obj,
+                                            ScopedPrinter &Writer);
+
 std::unique_ptr<ObjDumper> createWasmDumper(const object::WasmObjectFile &Obj,
                                             ScopedPrinter &Writer);
 
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index ca633ceff90800e..472fdfa882b6059 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -27,6 +27,7 @@
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/COFFImportFile.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/GOFFObjectFile.h"
 #include "llvm/Object/MachOUniversal.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Object/Wasm.h"
@@ -344,6 +345,9 @@ createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) {
   if (const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(&Obj))
     return createMachODumper(*MachOObj, Writer);
 
+  if (const GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>(&Obj))
+    return createGOFFDumper(*GOFFObj, Writer);
+
   if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj))
     return createWasmDumper(*WasmObj, Writer);
 



More information about the llvm-commits mailing list