[llvm-branch-commits] [llvm] [llvm-readobj][ELF] Print the address of each --stack-sizes entry (PR #232331)

Prabhu Rajasekaran via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Oct 15 06:59:13 PDT 2026


https://github.com/Prabhuk updated https://github.com/llvm/llvm-project/pull/232331

>From eefa27be50eaa21da33bd9939aff8f7069c01b5a Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 15 Oct 2026 06:55:36 -0700
Subject: [PATCH] [llvm-readobj][ELF] Print the address of each --stack-sizes
 entry

In a linked file, print the function address that each .stack_sizes
entry holds as Address in the LLVM and JSON output. The entries can then
be matched with --call-graph-info output by address, without looking up
function names.

Assisted-by: Gemini
---
 .../tools/llvm-readobj/ELF/stack-sizes.test   | 27 ++++++++++++++++--
 llvm/tools/llvm-readobj/ELFDumper.cpp         | 28 +++++++++++++------
 2 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test b/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
index 8ce1a6f1b6b27..c9c5fd52142ea 100644
--- a/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
+++ b/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
@@ -176,8 +176,8 @@ Symbols:
 # SYM-LLVM-NEXT: ]
 
 ## Check that we correctly report the stack sizes in an executable (non-relocatable)
-## object file. This also shows that the sh_link field is ignored in this situation
-## without warning.
+## object file, with the address of each function in the LLVM and JSON output. This
+## also shows that the sh_link field is ignored in this situation without warning.
 
 # RUN: yaml2obj --docnum=2 %s -o %t02
 # RUN: llvm-readelf --stack-sizes %t02 2>&1 \
@@ -185,6 +185,8 @@ Symbols:
 # RUN:                  --match-full-lines --implicit-check-not=warning:
 # RUN: llvm-readobj --stack-sizes %t02 2>&1 \
 # RUN:   | FileCheck %s --check-prefix=EXEC-LLVM --implicit-check-not=warning:
+# RUN: llvm-readobj --elf-output-style=JSON --pretty-print --stack-sizes %t02 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=EXEC-JSON --implicit-check-not=warning:
 
 #      EXEC-GNU:         Size     Functions
 # EXEC-GNU-NEXT:           16     other
@@ -195,18 +197,32 @@ Symbols:
 # EXEC-LLVM:      StackSizes [
 # EXEC-LLVM-NEXT:   Entry {
 # EXEC-LLVM-NEXT:     Functions: [other]
+# EXEC-LLVM-NEXT:     Address: 0x0{{$}}
 # EXEC-LLVM-NEXT:     Size: 0x10
 # EXEC-LLVM-NEXT:   }
 # EXEC-LLVM-NEXT:   Entry {
 # EXEC-LLVM-NEXT:     Functions: [other_end]
+# EXEC-LLVM-NEXT:     Address: 0x10{{$}}
 # EXEC-LLVM-NEXT:     Size: 0x20
 # EXEC-LLVM-NEXT:   }
 # EXEC-LLVM-NEXT:   Entry {
 # EXEC-LLVM-NEXT:     Functions: [bar]
+# EXEC-LLVM-NEXT:     Address: 0x20{{$}}
 # EXEC-LLVM-NEXT:     Size: 0x30
 # EXEC-LLVM-NEXT:   }
 # EXEC-LLVM-NEXT: ]
 
+# EXEC-JSON:      "StackSizes": [
+# EXEC-JSON-NEXT:   {
+# EXEC-JSON-NEXT:     "Entry": {
+# EXEC-JSON-NEXT:       "Functions": [
+# EXEC-JSON-NEXT:         "other"
+# EXEC-JSON-NEXT:       ],
+# EXEC-JSON-NEXT:       "Address": 0,
+# EXEC-JSON-NEXT:       "Size": 16
+# EXEC-JSON-NEXT:     }
+# EXEC-JSON-NEXT:   },
+
 --- !ELF
 FileHeader:
   Class: ELFCLASS64
@@ -392,11 +408,13 @@ Symbols:
 # SUDDENEND-LLVM:      StackSizes [
 # SUDDENEND-LLVM-NEXT:   Entry {
 # SUDDENEND-LLVM-NEXT:     Functions: [foo]
+# SUDDENEND-LLVM-NEXT:     Address: 0x0{{$}}
 # SUDDENEND-LLVM-NEXT:     Size: 0x8
 # SUDDENEND-LLVM-NEXT:   }
 # SUDDENEND-LLVM-NEXT: warning: '[[FILE]]': SHT_PROGBITS section with index 2 ended while trying to extract a stack size entry
 # SUDDENEND-LLVM-NEXT:   Entry {
 # SUDDENEND-LLVM-NEXT:     Functions: [foo]
+# SUDDENEND-LLVM-NEXT:     Address: 0x0{{$}}
 # SUDDENEND-LLVM-NEXT:     Size: 0x8
 # SUDDENEND-LLVM-NEXT:   }
 # SUDDENEND-LLVM-NEXT: warning: '[[FILE]]': SHT_PROGBITS section with index 3 ended while trying to extract a stack size entry
@@ -638,14 +656,17 @@ Sections:
 # MULTIPLE-LLVM:      StackSizes [
 # MULTIPLE-LLVM-NEXT:   Entry {
 # MULTIPLE-LLVM-NEXT:     Functions: [other]
+# MULTIPLE-LLVM-NEXT:     Address: 0x0{{$}}
 # MULTIPLE-LLVM-NEXT:     Size: 0x10
 # MULTIPLE-LLVM-NEXT:   }
 # MULTIPLE-LLVM-NEXT:   Entry {
 # MULTIPLE-LLVM-NEXT:     Functions: [other_end]
+# MULTIPLE-LLVM-NEXT:     Address: 0x10{{$}}
 # MULTIPLE-LLVM-NEXT:     Size: 0x20
 # MULTIPLE-LLVM-NEXT:   }
 # MULTIPLE-LLVM-NEXT:   Entry {
 # MULTIPLE-LLVM-NEXT:     Functions: [bar]
+# MULTIPLE-LLVM-NEXT:     Address: 0x20{{$}}
 # MULTIPLE-LLVM-NEXT:     Size: 0x30
 # MULTIPLE-LLVM-NEXT:   }
 # MULTIPLE-LLVM-NEXT: ]
@@ -907,6 +928,7 @@ Sections:
 # MULTIPLE-SYMBOLS-LLVM:      StackSizes [
 # MULTIPLE-SYMBOLS-LLVM-NEXT:   Entry {
 # MULTIPLE-SYMBOLS-LLVM-NEXT:     Functions: [foo, bar]
+# MULTIPLE-SYMBOLS-LLVM-NEXT:     Address: 0x0{{$}}
 # MULTIPLE-SYMBOLS-LLVM-NEXT:     Size: 0x10
 # MULTIPLE-SYMBOLS-LLVM-NEXT:   }
 # MULTIPLE-SYMBOLS-LLVM-NEXT: ]
@@ -955,6 +977,7 @@ Symbols:
 # THUMB-LLVM:      StackSizes [
 # THUMB-LLVM-NEXT:   Entry {
 # THUMB-LLVM-NEXT:     Functions: [foo]
+# THUMB-LLVM-NEXT:     Address: 0x1000{{$}}
 # THUMB-LLVM-NEXT:     Size: 0x10
 # THUMB-LLVM-NEXT:   }
 # THUMB-LLVM-NEXT: ]
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 623ae0a98eb76..77f2eaa28b3fa 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -368,8 +368,12 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
                       unsigned Ndx, const Elf_Shdr *SymTab,
                       const Elf_Shdr *FunctionSec, const Elf_Shdr &StackSizeSec,
                       const RelocationResolver &Resolver, DataExtractor Data);
+  // Prints a stack size entry. Address is the function's address: the value
+  // stored in the entry in a linked file, or the value that its relocation
+  // resolves to in a relocatable file.
   virtual void printStackSizeEntry(uint64_t Size,
-                                   ArrayRef<std::string> FuncNames) = 0;
+                                   ArrayRef<std::string> FuncNames,
+                                   uint64_t Address) = 0;
 
   void printRelocatableStackSizes(std::function<void()> PrintHeader);
   void printNonRelocatableStackSizes(std::function<void()> PrintHeader);
@@ -749,8 +753,8 @@ template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> {
   void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec,
                                     const Twine &Label, unsigned EntriesNum);
 
-  void printStackSizeEntry(uint64_t Size,
-                           ArrayRef<std::string> FuncNames) override;
+  void printStackSizeEntry(uint64_t Size, ArrayRef<std::string> FuncNames,
+                           uint64_t Address) override;
 
   void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
   void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
@@ -806,8 +810,8 @@ template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> {
                    bool /*ExtraSymInfo*/) const override;
   void printProgramHeaders() override;
   void printSectionMapping() override {}
-  void printStackSizeEntry(uint64_t Size,
-                           ArrayRef<std::string> FuncNames) override;
+  void printStackSizeEntry(uint64_t Size, ArrayRef<std::string> FuncNames,
+                           uint64_t Address) override;
   void printCallGraphRelocation(const CallGraphFunc<ELFT> &Func,
                                 const Elf_Shdr &RelSec, const Elf_Shdr &SymTab);
   // Returns the names of the functions at the address that the relocation for
@@ -7258,12 +7262,12 @@ bool ELFDumper<ELFT>::printFunctionStackSize(
   }
 
   if (FuncSymIndexes.empty()) {
-    printStackSizeEntry(StackSize, {"?"});
+    printStackSizeEntry(StackSize, {"?"}, SymValue);
   } else {
     SmallVector<std::string> FuncSymNames;
     for (uint32_t Index : FuncSymIndexes)
       FuncSymNames.push_back(this->getStaticSymbolName(Index));
-    printStackSizeEntry(StackSize, FuncSymNames);
+    printStackSizeEntry(StackSize, FuncSymNames, SymValue);
   }
 
   return true;
@@ -7271,7 +7275,8 @@ bool ELFDumper<ELFT>::printFunctionStackSize(
 
 template <class ELFT>
 void GNUELFDumper<ELFT>::printStackSizeEntry(uint64_t Size,
-                                             ArrayRef<std::string> FuncNames) {
+                                             ArrayRef<std::string> FuncNames,
+                                             uint64_t /*Address*/) {
   OS.PadToColumn(2);
   OS << format_decimal(Size, 11);
   OS.PadToColumn(18);
@@ -9001,9 +9006,14 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printStackSizes() {
 
 template <class ELFT>
 void LLVMELFDumper<ELFT>::printStackSizeEntry(uint64_t Size,
-                                              ArrayRef<std::string> FuncNames) {
+                                              ArrayRef<std::string> FuncNames,
+                                              uint64_t Address) {
   DictScope D(W, "Entry");
   W.printList("Functions", FuncNames);
+  // In a linked file, the function is identified by its address, as in
+  // --call-graph-info.
+  if (this->Obj.getHeader().e_type != ELF::ET_REL)
+    W.printHex("Address", Address);
   W.printHex("Size", Size);
 }
 



More information about the llvm-branch-commits mailing list