[llvm] [llvm-nm][GOFF] Support symbol types and sizes (PR #207119)

Amy Kwan via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 28 07:31:45 PDT 2026


https://github.com/amy-kwan updated https://github.com/llvm/llvm-project/pull/207119

>From 0a692c21514b41fcc1d671ed01085f7ac93cfeb4 Mon Sep 17 00:00:00 2001
From: Amy Kwan <amy.kwan1 at ibm.com>
Date: Thu, 2 Jul 2026 01:00:00 -0400
Subject: [PATCH 1/4] [llvm-nm][GOFF] Support symbol types and sizes

Add GOFF-specific handling in llvm-nm for symbol types and sizes.
GOFF symbols are now classified using their GOFF type, allowing llvm-nm to
distinguish global/local data and text symbol,s as well as undefined symbols.

This addition to llvm-nm is also useful to display the symbol table of GOFF
object and archives.
---
 .../llvm-nm/GOFF/symbol-types-and-sizes.ll    | 42 ++++++++++++++++++
 llvm/tools/llvm-nm/llvm-nm.cpp                | 44 ++++++++++++++++++-
 2 files changed, 85 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll

diff --git a/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll b/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll
new file mode 100644
index 0000000000000..405520a961a67
--- /dev/null
+++ b/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll
@@ -0,0 +1,42 @@
+; REQUIRES: systemz-registered-target
+; REQUIRES: target=s390x{{.*}}
+
+; RUN: llc -mtriple=s390x-ibm-zos -filetype=obj %s -o %t.o
+; RUN: llvm-nm --no-sort %t.o | FileCheck %s --check-prefix=TYPES
+; RUN: llvm-nm --no-sort --print-size --defined-only %t.o | FileCheck %s --check-prefix=SIZES
+
+target triple = "s390x-ibm-zos"
+
+ at GlobalData = global i32 42, align 4
+ at LocalData = internal global i32 7, align 4
+
+declare void @ExternFunc()
+
+define void @GlobalFunc() {
+entry:
+  ret void
+}
+
+define internal void @LocalFunc() {
+entry:
+  ret void
+}
+
+define void @UseExternFunc() {
+entry:
+  call void @ExternFunc()
+  ret void
+}
+
+; TYPES-DAG: {{^[0-9A-Fa-f]+}} D GlobalData
+; TYPES-DAG: {{^[0-9A-Fa-f]+}} d LocalData
+; TYPES-DAG: {{^[0-9A-Fa-f]+}} T GlobalFunc
+; TYPES-DAG: {{^[0-9A-Fa-f]+}} t LocalFunc
+; TYPES-DAG: {{^[0-9A-Fa-f]+}} T UseExternFunc
+; TYPES-DAG: {{^ *}}U ExternFunc
+
+; SIZES-DAG: {{^[0-9A-Fa-f]+}} {{0*4}} D GlobalData
+; SIZES-DAG: {{^[0-9A-Fa-f]+}} {{0*4}} d LocalData
+; SIZES-DAG: {{^[0-9A-Fa-f]+}} {{[0-9A-Fa-f]+}} T GlobalFunc
+; SIZES-DAG: {{^[0-9A-Fa-f]+}} {{[0-9A-Fa-f]+}} t LocalFunc
+; SIZES-DAG: {{^[0-9A-Fa-f]+}} {{[0-9A-Fa-f]+}} T UseExternFunc
diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp
index 4e3472154063a..2979fc4a0bcb3 100644
--- a/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -28,6 +28,7 @@
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/COFFImportFile.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/GOFFObjectFile.h"
 #include "llvm/Object/IRObjectFile.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/MachOUniversal.h"
@@ -1013,6 +1014,42 @@ static char getSymbolNMTypeChar(COFFImportFile &Obj) {
   return '?';
 }
 
+static char getSymbolNMTypeChar(GOFFObjectFile &Obj, basic_symbol_iterator I) {
+  symbol_iterator SymI(I);
+  Expected<section_iterator> SecIOrErr = SymI->getSection();
+  if (!SecIOrErr) {
+    consumeError(SecIOrErr.takeError());
+    return '?';
+  }
+
+  GOFFSymbolRef Ref(*I);
+  Expected<uint32_t> Flags = Ref.getSymbolGOFFFlags();
+  Expected<SymbolRef::Type> Type = Ref.getSymbolGOFFType();
+
+  if (!Type || !Flags) {
+    return '?';
+  }
+
+  switch (*Type) {
+  case SymbolRef::ST_Unknown:
+    return 'U';
+  case SymbolRef::ST_Data: {
+    if (*Flags & SymbolRef::SF_Global)
+      return 'D';
+    return 'd';
+  }
+  case SymbolRef::ST_Debug:
+    return 'g';
+  case SymbolRef::ST_Function: {
+    if (*Flags & SymbolRef::SF_Global)
+      return 'T';
+    return 't';
+  }
+  default:
+    return 'o';
+  }
+}
+
 static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
   DataRefImpl Symb = I->getRawDataRefImpl();
   uint8_t NType = Obj.is64Bit() ? Obj.getSymbol64TableEntry(Symb).n_type
@@ -1173,7 +1210,9 @@ static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,
     Ret = getSymbolNMTypeChar(*ELF, I);
     if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE)
       return Ret;
-  } else
+  } else if (GOFFObjectFile *GOFF = dyn_cast<GOFFObjectFile>(&Obj))
+    Ret = getSymbolNMTypeChar(*GOFF, I);
+  else
     llvm_unreachable("unknown binary format");
 
   if (!(Symflags & object::SymbolRef::SF_Global))
@@ -1852,6 +1891,9 @@ static bool getSymbolNamesFromObject(SymbolicFile &Obj,
       S.Address = 0;
       if (isa<ELFObjectFileBase>(&Obj))
         S.Size = ELFSymbolRef(Sym).getSize();
+      else if (isa<GOFFObjectFile>(&Obj)) {
+        S.Size = GOFFSymbolRef(Sym).getSize();
+      }
 
       if (const XCOFFObjectFile *XCOFFObj =
               dyn_cast<const XCOFFObjectFile>(&Obj))

>From 66d6934940eac0c087a1c44f5e01f94cd99f63a1 Mon Sep 17 00:00:00 2001
From: Amy Kwan <amy.kwan1 at ibm.com>
Date: Tue, 14 Jul 2026 12:09:43 -0400
Subject: [PATCH 2/4] Address review comments: remove unnecessary code, fix
 braces.

---
 llvm/tools/llvm-nm/llvm-nm.cpp | 38 ++++++++--------------------------
 1 file changed, 9 insertions(+), 29 deletions(-)

diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp
index 2979fc4a0bcb3..591dec3fc4109 100644
--- a/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -1014,39 +1014,20 @@ static char getSymbolNMTypeChar(COFFImportFile &Obj) {
   return '?';
 }
 
-static char getSymbolNMTypeChar(GOFFObjectFile &Obj, basic_symbol_iterator I) {
-  symbol_iterator SymI(I);
-  Expected<section_iterator> SecIOrErr = SymI->getSection();
-  if (!SecIOrErr) {
-    consumeError(SecIOrErr.takeError());
-    return '?';
-  }
-
+static char getSymbolNMTypeChar(GOFFObjectFile &, basic_symbol_iterator I) {
   GOFFSymbolRef Ref(*I);
-  Expected<uint32_t> Flags = Ref.getSymbolGOFFFlags();
   Expected<SymbolRef::Type> Type = Ref.getSymbolGOFFType();
-
-  if (!Type || !Flags) {
+  if (!Type) {
+    consumeError(Type.takeError());
     return '?';
   }
-
   switch (*Type) {
-  case SymbolRef::ST_Unknown:
-    return 'U';
-  case SymbolRef::ST_Data: {
-    if (*Flags & SymbolRef::SF_Global)
-      return 'D';
+  case SymbolRef::ST_Data:
     return 'd';
-  }
-  case SymbolRef::ST_Debug:
-    return 'g';
-  case SymbolRef::ST_Function: {
-    if (*Flags & SymbolRef::SF_Global)
-      return 'T';
+  case SymbolRef::ST_Function:
     return 't';
-  }
   default:
-    return 'o';
+    return '?';
   }
 }
 
@@ -1210,9 +1191,9 @@ static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,
     Ret = getSymbolNMTypeChar(*ELF, I);
     if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE)
       return Ret;
-  } else if (GOFFObjectFile *GOFF = dyn_cast<GOFFObjectFile>(&Obj))
+  } else if (GOFFObjectFile *GOFF = dyn_cast<GOFFObjectFile>(&Obj)) {
     Ret = getSymbolNMTypeChar(*GOFF, I);
-  else
+  } else
     llvm_unreachable("unknown binary format");
 
   if (!(Symflags & object::SymbolRef::SF_Global))
@@ -1891,9 +1872,8 @@ static bool getSymbolNamesFromObject(SymbolicFile &Obj,
       S.Address = 0;
       if (isa<ELFObjectFileBase>(&Obj))
         S.Size = ELFSymbolRef(Sym).getSize();
-      else if (isa<GOFFObjectFile>(&Obj)) {
+      else if (isa<GOFFObjectFile>(&Obj))
         S.Size = GOFFSymbolRef(Sym).getSize();
-      }
 
       if (const XCOFFObjectFile *XCOFFObj =
               dyn_cast<const XCOFFObjectFile>(&Obj))

>From a98bda8a536784b5040ee285276de87343490aec Mon Sep 17 00:00:00 2001
From: Amy Kwan <amy.kwan1 at ibm.com>
Date: Mon, 27 Jul 2026 13:09:25 -0400
Subject: [PATCH 3/4] Remove extra requires line

---
 llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll b/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll
index 405520a961a67..6969e34c436cf 100644
--- a/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll
+++ b/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll
@@ -1,5 +1,4 @@
 ; REQUIRES: systemz-registered-target
-; REQUIRES: target=s390x{{.*}}
 
 ; RUN: llc -mtriple=s390x-ibm-zos -filetype=obj %s -o %t.o
 ; RUN: llvm-nm --no-sort %t.o | FileCheck %s --check-prefix=TYPES

>From ad5cf69429c6503703e590627410df7c90de3f21 Mon Sep 17 00:00:00 2001
From: Amy Kwan <amy.kwan1 at ibm.com>
Date: Tue, 28 Jul 2026 10:31:27 -0400
Subject: [PATCH 4/4] Use llvm_unreachable and update LIT test.

---
 .../llvm-nm/GOFF/symbol-types-and-sizes.ll    | 21 +++++++------------
 llvm/tools/llvm-nm/llvm-nm.cpp                |  2 +-
 2 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll b/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll
index 6969e34c436cf..4f8c36726c666 100644
--- a/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll
+++ b/llvm/test/tools/llvm-nm/GOFF/symbol-types-and-sizes.ll
@@ -1,8 +1,7 @@
 ; REQUIRES: systemz-registered-target
 
 ; RUN: llc -mtriple=s390x-ibm-zos -filetype=obj %s -o %t.o
-; RUN: llvm-nm --no-sort %t.o | FileCheck %s --check-prefix=TYPES
-; RUN: llvm-nm --no-sort --print-size --defined-only %t.o | FileCheck %s --check-prefix=SIZES
+; RUN: llvm-nm --no-sort --print-size %t.o | FileCheck %s
 
 target triple = "s390x-ibm-zos"
 
@@ -27,15 +26,9 @@ entry:
   ret void
 }
 
-; TYPES-DAG: {{^[0-9A-Fa-f]+}} D GlobalData
-; TYPES-DAG: {{^[0-9A-Fa-f]+}} d LocalData
-; TYPES-DAG: {{^[0-9A-Fa-f]+}} T GlobalFunc
-; TYPES-DAG: {{^[0-9A-Fa-f]+}} t LocalFunc
-; TYPES-DAG: {{^[0-9A-Fa-f]+}} T UseExternFunc
-; TYPES-DAG: {{^ *}}U ExternFunc
-
-; SIZES-DAG: {{^[0-9A-Fa-f]+}} {{0*4}} D GlobalData
-; SIZES-DAG: {{^[0-9A-Fa-f]+}} {{0*4}} d LocalData
-; SIZES-DAG: {{^[0-9A-Fa-f]+}} {{[0-9A-Fa-f]+}} T GlobalFunc
-; SIZES-DAG: {{^[0-9A-Fa-f]+}} {{[0-9A-Fa-f]+}} t LocalFunc
-; SIZES-DAG: {{^[0-9A-Fa-f]+}} {{[0-9A-Fa-f]+}} T UseExternFunc
+; CHECK-DAG: {{^[0-9A-Fa-f]+}} {{0*4}} D GlobalData
+; CHECK-DAG: {{^[0-9A-Fa-f]+}} {{0*4}} d LocalData
+; CHECK-DAG: {{^[0-9A-Fa-f]+}} {{[0-9A-Fa-f]+}} T GlobalFunc
+; CHECK-DAG: {{^[0-9A-Fa-f]+}} {{[0-9A-Fa-f]+}} t LocalFunc
+; CHECK-DAG: {{^[0-9A-Fa-f]+}} {{[0-9A-Fa-f]+}} T UseExternFunc
+; CHECK-DAG: {{^ *}}U ExternFunc
diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp
index 591dec3fc4109..e0a5aae9e265d 100644
--- a/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -1027,7 +1027,7 @@ static char getSymbolNMTypeChar(GOFFObjectFile &, basic_symbol_iterator I) {
   case SymbolRef::ST_Function:
     return 't';
   default:
-    return '?';
+    llvm_unreachable("GOFFObjectFile::getSymbolType returned unexpected type");
   }
 }
 



More information about the llvm-commits mailing list