[llvm-branch-commits] [llvm] release/22.x: Revert "[llvm-readobj] Dump callgraph section info for ELF" (#176221) (PR #176228)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Jan 15 11:34:35 PST 2026


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/176228

Backport 97576a86eb25696a2b57cd42370991b172c08405

Requested by: @Prabhuk

>From 6323ec3c6e5a90ed5c62d892fec09391f48468f1 Mon Sep 17 00:00:00 2001
From: Prabhu Rajasekaran <prabhukr at google.com>
Date: Thu, 15 Jan 2026 11:24:19 -0800
Subject: [PATCH] Revert "[llvm-readobj] Dump callgraph section info for ELF"
 (#176221)

Reverts llvm/llvm-project#157499

Following up on discourse post. Reverting this patch and will attempt a
reland addressing post merge comments.

(cherry picked from commit 97576a86eb25696a2b57cd42370991b172c08405)
---
 llvm/docs/CommandGuide/llvm-readelf.rst       |  16 +-
 llvm/docs/CommandGuide/llvm-readobj.rst       |  42 +-
 .../ELF/call-graph-info-warn-malformed.test   | 366 ------------
 .../llvm-readobj/ELF/call-graph-info.test     | 521 ------------------
 llvm/tools/llvm-readobj/ELFDumper.cpp         | 278 +---------
 llvm/tools/llvm-readobj/ObjDumper.h           |   1 -
 llvm/tools/llvm-readobj/Opts.td               |   1 -
 llvm/tools/llvm-readobj/llvm-readobj.cpp      |   4 -
 8 files changed, 22 insertions(+), 1207 deletions(-)
 delete mode 100644 llvm/test/tools/llvm-readobj/ELF/call-graph-info-warn-malformed.test
 delete mode 100644 llvm/test/tools/llvm-readobj/ELF/call-graph-info.test

diff --git a/llvm/docs/CommandGuide/llvm-readelf.rst b/llvm/docs/CommandGuide/llvm-readelf.rst
index ed349d1d15761..5403fea60d5ee 100644
--- a/llvm/docs/CommandGuide/llvm-readelf.rst
+++ b/llvm/docs/CommandGuide/llvm-readelf.rst
@@ -38,18 +38,6 @@ OPTIONS
  Display the contents of the basic block address map section(s), which contain the
  address of each function, along with the relative offset of each basic block.
 
-.. option:: --call-graph-info
-
-  Display the call graph section entries i.e. for each function
-  its identifying information, each of its direct callees' information
-  and for each indirect callee a 64 bit number representing the callee's
-  function signature. This information can be used to reconstruct
-  the program call graph.
-
-.. option:: --cg-profile
-
- Display the callgraph profile section.
-
 .. option:: --decompress, -z
 
   Dump decompressed section content when used with ``-x`` or ``-p``.
@@ -75,6 +63,10 @@ OPTIONS
 
  Display the dynamic table.
 
+.. option:: --cg-profile
+
+ Display the callgraph profile section.
+
 .. option:: --histogram, -I
 
  Display a bucket list histogram for dynamic symbol hash tables.
diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst
index 4fb2901676898..0d05b947a6b3e 100644
--- a/llvm/docs/CommandGuide/llvm-readobj.rst
+++ b/llvm/docs/CommandGuide/llvm-readobj.rst
@@ -181,17 +181,13 @@ The following options are implemented only for the ELF file format.
  When pgo analysis maps are present, all analyses are printed as their raw
  value.
 
- .. option:: --call-graph-info
-
-  Display the call graph section entries i.e. for each function
-  its identifying information, each of its direct callees' information
-  and for each indirect callee a 64 bit number representing the callee's
-  function signature. This information can be used to reconstruct
-  the program call graph.
+.. option:: --pretty-pgo-analysis-map
 
-.. option:: --cg-profile
+ When pgo analysis maps are present in the basic block address map section(s),
+ analyses with special formats (i.e. BlockFrequency, BranchProbability, etc)
+ are printed using the same format as their respective analysis pass.
 
- Display the callgraph profile section.
+ Requires :option:`--bb-addr-map` to have an effect.
 
 .. option:: --dependent-libraries
 
@@ -209,6 +205,14 @@ The following options are implemented only for the ELF file format.
 
  Display the dynamic table.
 
+.. option:: --cg-profile
+
+ Display the callgraph profile section.
+
+.. option:: --histogram, -I
+
+ Display a bucket list histogram for dynamic symbol hash tables.
+
 .. option:: --elf-linker-options
 
  Display the linker options section.
@@ -220,6 +224,10 @@ The following options are implemented only for the ELF file format.
  structured format. ``GNU`` output mimics the equivalent GNU :program:`readelf`
  output. ``JSON`` is JSON formatted output intended for machine consumption.
 
+.. option:: --section-groups, -g
+
+ Display section groups.
+
 .. option:: --gnu-hash-table
 
  Display the GNU hash table for dynamic symbols.
@@ -232,10 +240,6 @@ The following options are implemented only for the ELF file format.
 
  Display the hash table for dynamic symbols.
 
-.. option:: --histogram, -I
-
- Display a bucket list histogram for dynamic symbol hash tables.
-
 .. option:: --memtag
 
  Display information about memory tagging present in the binary. This includes
@@ -246,14 +250,6 @@ The following options are implemented only for the ELF file format.
 
  Display all notes.
 
-.. option:: --pretty-pgo-analysis-map
-
- When pgo analysis maps are present in the basic block address map section(s),
- analyses with special formats (i.e. BlockFrequency, BranchProbability, etc)
- are printed using the same format as their respective analysis pass.
-
- Requires :option:`--bb-addr-map` to have an effect.
-
 .. option:: --pretty-print
 
  When used with :option:`--elf-output-style`, JSON output will be formatted in
@@ -263,10 +259,6 @@ The following options are implemented only for the ELF file format.
 
  Display the program headers.
 
-.. option:: --section-groups, -g
-
- Display section groups.
-
 .. option:: --section-mapping
 
  Display the section to segment mapping.
diff --git a/llvm/test/tools/llvm-readobj/ELF/call-graph-info-warn-malformed.test b/llvm/test/tools/llvm-readobj/ELF/call-graph-info-warn-malformed.test
deleted file mode 100644
index 63ef662f1a45b..0000000000000
--- a/llvm/test/tools/llvm-readobj/ELF/call-graph-info-warn-malformed.test
+++ /dev/null
@@ -1,366 +0,0 @@
-## Tests that --call-graph-info produces useful warnings
-## if SHT_LLVM_CALL_GRAPH type section processing idenitifies
-## malformed content.
-
-## Tests that --call-graph-info warns if there is no section of type SHT_LLVM_CALL_GRAPH.
-# RUN: yaml2obj --docnum=1 %s -o %t1
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t1 2>&1 | FileCheck %s -DFILE=%t1 --check-prefix=WARN_NO_SECTION
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t1 2>&1 | FileCheck %s -DFILE=%t1 --check-prefix=WARN_NO_SECTION
-
-# WARN_NO_SECTION: warning: '[[FILE]]': no SHT_LLVM_CALL_GRAPH section found
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_DYN
-  Machine:  EM_X86_64
-Sections:
-  - Name:  .text
-    Type:  SHT_PROGBITS
-    Size:  5
-Symbols:
-  - Name:  foo
-...
-
-## Check format version number.
-# RUN: yaml2obj --docnum=2 %s -o %t2
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=WARN_FMT_VERSION
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=WARN_FMT_VERSION
-
-# WARN_FMT_VERSION: warning: '[[FILE]]': unknown format version value [1] in SHT_LLVM_CALL_GRAPH type section
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_DYN
-  Machine:  EM_X86_64
-Sections:
-  - Name:  .text
-    Type:  SHT_PROGBITS
-    Size:  5
-  - Name:  .llvm.callgraph
-    Type:  SHT_LLVM_CALL_GRAPH
-    ContentArray: [
-      # --- Entry 1: foo (foo) ---
-      0x01, # Format Version - only supported value is 0x00
-    ]
-Symbols:
-  - Name:  foo
-...
-
-## Check missing flags.
-# RUN: yaml2obj --docnum=3 %s -o %t3
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=WARN_MISSING_FLAG
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=WARN_MISSING_FLAG
-
-# WARN_MISSING_FLAG: warning: '[[FILE]]': failed while reading call graph info's Flags unexpected end of data at offset 0x1 while reading [0x1, 0x2)
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_DYN
-  Machine:  EM_X86_64
-Sections:
-  - Name:  .text
-    Type:  SHT_PROGBITS
-    Size:  5
-  - Name:  .llvm.callgraph
-    Type:  SHT_LLVM_CALL_GRAPH
-    ContentArray: [
-      # --- Entry 1: foo (foo) ---
-      0x00, # Format Version
-      #< Missing flags
-    ]
-Symbols:
-  - Name:  foo
-...
-
-## Check Flags.
-# RUN: yaml2obj --docnum=4 %s -o %t4
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t4 2>&1 | FileCheck %s -DFILE=%t4 --check-prefix=WARN_FLAG
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t4 2>&1 | FileCheck %s -DFILE=%t4 --check-prefix=WARN_FLAG
-
-# WARN_FLAG: warning: '[[FILE]]': unexpected Flags value [8]
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_DYN
-  Machine:  EM_X86_64
-Sections:
-  - Name:  .text
-    Type:  SHT_PROGBITS
-    Size:  5
-  - Name:  .llvm.callgraph
-    Type:  SHT_LLVM_CALL_GRAPH
-    ContentArray: [
-      # --- Entry 1: foo (foo) ---
-      0x00, # Format Version
-      0x08, # Flags - only valid values are 0x00 to 0x07
-    ]
-Symbols:
-  - Name:  foo
-...
-
-## Check missing function entry PC.
-# RUN: yaml2obj --docnum=5 %s -o %t5
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t5 2>&1 | FileCheck %s -DFILE=%t5 --check-prefix=WARN_MISSING_PC
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t5 2>&1 | FileCheck %s -DFILE=%t5 --check-prefix=WARN_MISSING_PC
-
-# WARN_MISSING_PC: warning: '[[FILE]]': failed while reading call graph info function entry PC unexpected end of data at offset 0x2 while reading [0x2, 0xa)
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_DYN
-  Machine:  EM_X86_64
-Sections:
-  - Name:  .text
-    Type:  SHT_PROGBITS
-    Size:  5
-  - Name:  .llvm.callgraph
-    Type:  SHT_LLVM_CALL_GRAPH
-    ContentArray: [
-      # --- Entry 1: foo (foo) ---
-      0x00, # Format Version
-      0x00, # Flags
-      #< Missing function entry PC
-    ]
-Symbols:
-  - Name:  foo
-...
-
-## Check missing function Type ID.
-# RUN: yaml2obj --docnum=6 %s -o %t6
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t6 2>&1 | FileCheck %s -DFILE=%t6 --check-prefix=WARN_MISSING_TYPEID
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t6 2>&1 | FileCheck %s -DFILE=%t6 --check-prefix=WARN_MISSING_TYPEID
-
-# WARN_MISSING_TYPEID: warning: '[[FILE]]': failed while reading function type ID unexpected end of data at offset 0xa while reading [0xa, 0x12)
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_DYN
-  Machine:  EM_X86_64
-Sections:
-  - Name:  .text
-    Type:  SHT_PROGBITS
-    Size:  5
-  - Name:  .llvm.callgraph
-    Type:  SHT_LLVM_CALL_GRAPH
-    ContentArray: [
-      # --- Entry 1: foo (foo) ---
-      0x00, # Format Version
-      0x00, # Flags
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Function entry address
-      #< Missing Type ID
-    ]
-Symbols:
-  - Name:  foo
-...
-
-## Check missing number of direct callees.
-# RUN: yaml2obj --docnum=7 %s -o %t7
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t7 2>&1 | FileCheck %s -DFILE=%t7 --check-prefix=WARN_MISSING_DIRECT
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t7 2>&1 | FileCheck %s -DFILE=%t7 --check-prefix=WARN_MISSING_DIRECT
-
-# WARN_MISSING_DIRECT: warning: '[[FILE]]': failed while reading number of direct callees unable to decode LEB128 at offset 0x00000012: malformed uleb128, extends past end
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_DYN
-  Machine:  EM_X86_64
-Sections:
-  - Name:  .text
-    Type:  SHT_PROGBITS
-    Size:  5
-  - Name:  .llvm.callgraph
-    Type:  SHT_LLVM_CALL_GRAPH
-    ContentArray: [
-      # --- Entry 1: foo (foo) ---
-      0x00, # Format Version
-      0x02, # Flags (HasDirectCallees)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Function entry address
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # TypeID unknown
-      #< Missing NumDirectCallees (ULEB128)
-    ]
-Symbols:
-  - Name:  foo
-...
-
-## Check missing direct callee.
-# RUN: yaml2obj --docnum=8 %s -o %t8
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t8 2>&1 | FileCheck %s -DFILE=%t8 --check-prefix=WARN_MISSING_CALLEE
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t8 2>&1 | FileCheck %s -DFILE=%t8 --check-prefix=WARN_MISSING_CALLEE
-
-# WARN_MISSING_CALLEE: warning: '[[FILE]]': failed while reading direct callee unexpected end of data at offset 0x13 while reading [0x13, 0x1b)
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_DYN
-  Machine:  EM_X86_64
-Sections:
-  - Name:  .text
-    Type:  SHT_PROGBITS
-    Size:  5
-  - Name:  .llvm.callgraph
-    Type:  SHT_LLVM_CALL_GRAPH
-    ContentArray: [
-      # --- Entry 1: foo (foo) ---
-      0x00, # Format Version
-      0x02, # Flags (HasDirectCallees)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Function entry address
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # TypeID unknown
-      0x01, # NumDirectCallees
-      #< Missing direct callee address
-    ]
-Symbols:
-  - Name:  foo
-...
-
-## Check missing number of indirect target type IDs.
-# RUN: yaml2obj --docnum=9 %s -o %t9
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t9 2>&1 | FileCheck %s -DFILE=%t9 --check-prefix=WARN_MISSING_NUM_INDIRECT
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t9 2>&1 | FileCheck %s -DFILE=%t9 --check-prefix=WARN_MISSING_NUM_INDIRECT
-
-# WARN_MISSING_NUM_INDIRECT: warning: '[[FILE]]': failed while reading number of indirect target type IDs unable to decode LEB128 at offset 0x00000012: malformed uleb128, extends past end
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_DYN
-  Machine:  EM_X86_64
-Sections:
-  - Name:  .text
-    Type:  SHT_PROGBITS
-    Size:  5
-  - Name:  .llvm.callgraph
-    Type:  SHT_LLVM_CALL_GRAPH
-    ContentArray: [
-      # --- Entry 1: foo (foo) ---
-      0x00, # Format Version
-      0x04, # Flags (HasIndirectCallees)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Function entry address
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # TypeID unknown
-      #< Missing NumIndirectTargetTypeIDs (ULEB128)
-    ]
-Symbols:
-  - Name:  foo
-...
-
-## Check missing indirect target type ID.
-# RUN: yaml2obj --docnum=10 %s -o %t10
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t10 2>&1 | FileCheck %s -DFILE=%t10 --check-prefix=WARN_MISSING_INDIRECT_TARGET_TYPE_ID
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t10 2>&1 | FileCheck %s -DFILE=%t10 --check-prefix=WARN_MISSING_INDIRECT_TARGET_TYPE_ID
-
-# WARN_MISSING_INDIRECT_TARGET_TYPE_ID: warning: '[[FILE]]': failed while reading indirect target type ID unexpected end of data at offset 0x13 while reading [0x13, 0x1b)
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_REL
-  Machine:  EM_X86_64
-Sections:
-  - Name:  .text
-    Type:  SHT_PROGBITS
-    Size:  5
-  - Name:  .llvm.callgraph
-    Type:  SHT_LLVM_CALL_GRAPH
-    ContentArray: [
-      # --- Entry 1: foo (foo) ---
-      0x00, # Format Version
-      0x04, # Flags (HasIndirectCallees)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Function entry address
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # TypeID unknown
-      0x01, # NumIndirectTargetTypeIDs (1)
-      #< Missing indirect call entries here.
-    ]
-Symbols:
-  - Name:  foo
-...
-
-## Check missing relocation information.
-# RUN: yaml2obj --docnum=11 %s -o %t11
-# RUN: llvm-readelf --call-graph-info %t11 2>&1 | count 0
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t11 2>&1 | FileCheck %s -DFILE=%t11 --check-prefix=WARN_NO_RELOC
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t11 2>&1 | FileCheck %s -DFILE=%t11 --check-prefix=WARN_NO_RELOC
-
-# WARN_NO_RELOC: warning: '[[FILE]]': SHT_LLVM_CALL_GRAPH type section has unknown type id for 2 indirect targets
-# WARN_NO_RELOC: warning: '[[FILE]]': unknown relocation at offset 2
-# WARN_NO_RELOC: warning: '[[FILE]]': unknown relocation at offset 19
-# WARN_NO_RELOC: warning: '[[FILE]]': unknown relocation at offset 29
-# WARN_NO_RELOC: warning: '[[FILE]]': unknown relocation at offset 56
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_REL
-  Machine:  EM_X86_64
-Sections:
-  - Name: .text
-    Type: SHT_PROGBITS
-    Size: 12 # or whatever size is needed for all the data
-  - Name: .llvm.callgraph
-    Type: SHT_LLVM_CALL_GRAPH
-    ContentArray: [
-        '0', # Format version number
-        '3', # Flag IsIndirectTarget true, HasDirectCallees true
-        '0', '0', '0', '0', '0', '0', '0', '0', # foo()'s address
-        '0', '0', '0', '0', '0', '0', '0', '0', # foo()'s TypeID Unknown
-        '1', # NumDirectCallees
-        '0', '0', '0', '0', '0', '0', '0', '0', # Direct callee foo()'s address
-        '0', # Format version number
-        '5', # Flag IsIndirectTarget true, HasIndirectTargetTypeIDs true
-        '6', '0', '0', '0', '0', '0', '0', '0', # bar()'s address
-        '0', '0', '0', '0', '0', '0', '0', '0', # bar()'s TypeID Unknown
-        '1', # NumIndirectTargetTypeIDs
-        '16', '0', '0', '0', '0', '0', '0', '0', # Indirect callee type ID
-        '0', # Format version number
-        '1', # Flag IsIndirectTarget true
-        '10', '0', '0', '0', '0', '0', '0', '0', # baz()'s address
-        '32', '0', '0', '0', '0', '0', '0', '0', # baz()'s TypeID Unknown
-      ]
-  - Name:   .rela.llvm.callgraph
-    Type:   SHT_RELA
-    Flags:  [ SHF_INFO_LINK ]
-    Link:   .symtab
-    Relocations:
-      # 1. Pointer to foo() definition
-      - Offset: 0x2
-        Symbol: foo
-        Type:   R_X86_64_64
-
-      # 2. Pointer to the call site "callq foo" (offset 5 inside foo)
-      #    We relocate against 'foo' and add 5 to get the address of the instruction.
-      - Offset: 0x13
-        Symbol: foo
-        Type:   R_X86_64_64
-        Addend: 5
-
-      # 3. Pointer to bar() definition
-      - Offset: 0x1D
-        Symbol: bar
-        Type:   R_X86_64_64
-
-      # 4. Pointer to baz() definition
-      - Offset: 0x38
-        Symbol: baz
-        Type:   R_X86_64_64
-Symbols:
-  - Name:  foo
-  - Name:  bar
-  - Name:  baz
-...
diff --git a/llvm/test/tools/llvm-readobj/ELF/call-graph-info.test b/llvm/test/tools/llvm-readobj/ELF/call-graph-info.test
deleted file mode 100644
index 7226dd8ddea89..0000000000000
--- a/llvm/test/tools/llvm-readobj/ELF/call-graph-info.test
+++ /dev/null
@@ -1,521 +0,0 @@
-## Tests how --call-graph-info prints the call graph information.
-
-## Check non-relocatable object file handling.
-# RUN: yaml2obj --docnum=1 %s -o %t1
-# RUN: llvm-readelf --call-graph-info %t1 2>&1 | FileCheck %s --match-full-lines --allow-empty --check-prefix=GNU_NONRELOC -DFILE=%t1
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t1 2>&1 | FileCheck %s --match-full-lines --check-prefix=LLVM_NONRELOC -DFILE=%t1
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t1 2>&1 | FileCheck %s --match-full-lines --check-prefix=JSON_NONRELOC -DFILE=%t1
-
-## We do not support GNU format console output for --call-graph-info as it is an LLVM only info.
-# GNU_NONRELOC-NOT: .
-
-# LLVM_NONRELOC:      CallGraph [
-# LLVM_NONRELOC-NEXT:     Function {
-# LLVM_NONRELOC-NEXT:       Names: [foo]
-# LLVM_NONRELOC-NEXT:       Address: 0x1790
-# LLVM_NONRELOC-NEXT:       Version: 0
-# LLVM_NONRELOC-NEXT:       IsIndirectTarget: Yes
-# LLVM_NONRELOC-NEXT:       TypeId: 0x3ECBEEF531F74424
-# LLVM_NONRELOC-NEXT:       NumDirectCallees: 0
-# LLVM_NONRELOC-NEXT:       DirectCallees [
-# LLVM_NONRELOC-NEXT:       ]
-# LLVM_NONRELOC-NEXT:       NumIndirectTargetTypeIDs: 0
-# LLVM_NONRELOC-NEXT:       IndirectTypeIDs: []
-# LLVM_NONRELOC-NEXT:     }
-# LLVM_NONRELOC-NEXT:     Function {
-# LLVM_NONRELOC-NEXT:       Names: [bar]
-# LLVM_NONRELOC-NEXT:       Address: 0x17A0
-# LLVM_NONRELOC-NEXT:       Version: 0
-# LLVM_NONRELOC-NEXT:       IsIndirectTarget: Yes
-# LLVM_NONRELOC-NEXT:       TypeId: 0x3ECBEEF531F74424
-# LLVM_NONRELOC-NEXT:       NumDirectCallees: 0
-# LLVM_NONRELOC-NEXT:       DirectCallees [
-# LLVM_NONRELOC-NEXT:       ]
-# LLVM_NONRELOC-NEXT:       NumIndirectTargetTypeIDs: 0
-# LLVM_NONRELOC-NEXT:       IndirectTypeIDs: []
-# LLVM_NONRELOC-NEXT:     }
-# LLVM_NONRELOC-NEXT:     Function {
-# LLVM_NONRELOC-NEXT:       Names: [baz]
-# LLVM_NONRELOC-NEXT:       Address: 0x17B0
-# LLVM_NONRELOC-NEXT:       Version: 0
-# LLVM_NONRELOC-NEXT:       IsIndirectTarget: Yes
-# LLVM_NONRELOC-NEXT:       TypeId: 0x308E4B8159BC8654
-# LLVM_NONRELOC-NEXT:       NumDirectCallees: 0
-# LLVM_NONRELOC-NEXT:       DirectCallees [
-# LLVM_NONRELOC-NEXT:       ]
-# LLVM_NONRELOC-NEXT:       NumIndirectTargetTypeIDs: 0
-# LLVM_NONRELOC-NEXT:       IndirectTypeIDs: []
-# LLVM_NONRELOC-NEXT:     }
-# LLVM_NONRELOC-NEXT:     Function {
-# LLVM_NONRELOC-NEXT:       Names: [main]
-# LLVM_NONRELOC-NEXT:       Address: 0x17C0
-# LLVM_NONRELOC-NEXT:       Version: 0
-# LLVM_NONRELOC-NEXT:       IsIndirectTarget: Yes
-# LLVM_NONRELOC-NEXT:       TypeId: 0xFA6809609A76AFCA
-# LLVM_NONRELOC-NEXT:       NumDirectCallees: 3
-# LLVM_NONRELOC-NEXT:       DirectCallees [
-# LLVM_NONRELOC-NEXT:         {
-# LLVM_NONRELOC-NEXT:           Names: [foo]
-# LLVM_NONRELOC-NEXT:           Address: 0x1790
-# LLVM_NONRELOC-NEXT:         }
-# LLVM_NONRELOC-NEXT:         {
-# LLVM_NONRELOC-NEXT:           Names: [bar]
-# LLVM_NONRELOC-NEXT:           Address: 0x17A0
-# LLVM_NONRELOC-NEXT:         }
-# LLVM_NONRELOC-NEXT:         {
-# LLVM_NONRELOC-NEXT:           Names: [baz]
-# LLVM_NONRELOC-NEXT:           Address: 0x17B0
-# LLVM_NONRELOC-NEXT:         }
-# LLVM_NONRELOC-NEXT:       ]
-# LLVM_NONRELOC-NEXT:       NumIndirectTargetTypeIDs: 2
-# LLVM_NONRELOC-NEXT:       IndirectTypeIDs: [0x3ECBEEF531F74424, 0x308E4B8159BC8654]
-# LLVM_NONRELOC-NEXT:     }
-# LLVM_NONRELOC-NEXT:   ]
-
-# JSON_NONRELOC:     "CallGraph": [
-# JSON_NONRELOC-NEXT:      {
-# JSON_NONRELOC-NEXT:        "Function": {
-# JSON_NONRELOC-NEXT:          "Names": [
-# JSON_NONRELOC-NEXT:            "foo"
-# JSON_NONRELOC-NEXT:          ],
-# JSON_NONRELOC-NEXT:          "Address": 6032,
-# JSON_NONRELOC-NEXT:          "Version": 0,
-# JSON_NONRELOC-NEXT:          "IsIndirectTarget": true,
-# JSON_NONRELOC-NEXT:          "TypeId": 4524972987496481828,
-# JSON_NONRELOC-NEXT:          "NumDirectCallees": 0,
-# JSON_NONRELOC-NEXT:          "DirectCallees": [],
-# JSON_NONRELOC-NEXT:          "NumIndirectTargetTypeIDs": 0,
-# JSON_NONRELOC-NEXT:          "IndirectTypeIDs": []
-# JSON_NONRELOC-NEXT:        }
-# JSON_NONRELOC-NEXT:      },
-# JSON_NONRELOC-NEXT:      {
-# JSON_NONRELOC-NEXT:        "Function": {
-# JSON_NONRELOC-NEXT:          "Names": [
-# JSON_NONRELOC-NEXT:            "bar"
-# JSON_NONRELOC-NEXT:          ],
-# JSON_NONRELOC-NEXT:          "Address": 6048,
-# JSON_NONRELOC-NEXT:          "Version": 0,
-# JSON_NONRELOC-NEXT:          "IsIndirectTarget": true,
-# JSON_NONRELOC-NEXT:          "TypeId": 4524972987496481828,
-# JSON_NONRELOC-NEXT:          "NumDirectCallees": 0,
-# JSON_NONRELOC-NEXT:          "DirectCallees": [],
-# JSON_NONRELOC-NEXT:          "NumIndirectTargetTypeIDs": 0,
-# JSON_NONRELOC-NEXT:          "IndirectTypeIDs": []
-# JSON_NONRELOC-NEXT:        }
-# JSON_NONRELOC-NEXT:      },
-# JSON_NONRELOC-NEXT:      {
-# JSON_NONRELOC-NEXT:        "Function": {
-# JSON_NONRELOC-NEXT:          "Names": [
-# JSON_NONRELOC-NEXT:            "baz"
-# JSON_NONRELOC-NEXT:          ],
-# JSON_NONRELOC-NEXT:          "Address": 6064,
-# JSON_NONRELOC-NEXT:          "Version": 0,
-# JSON_NONRELOC-NEXT:          "IsIndirectTarget": true,
-# JSON_NONRELOC-NEXT:          "TypeId": 3498816979441845844,
-# JSON_NONRELOC-NEXT:          "NumDirectCallees": 0,
-# JSON_NONRELOC-NEXT:          "DirectCallees": [],
-# JSON_NONRELOC-NEXT:          "NumIndirectTargetTypeIDs": 0,
-# JSON_NONRELOC-NEXT:          "IndirectTypeIDs": []
-# JSON_NONRELOC-NEXT:        }
-# JSON_NONRELOC-NEXT:      },
-# JSON_NONRELOC-NEXT:      {
-# JSON_NONRELOC-NEXT:        "Function": {
-# JSON_NONRELOC-NEXT:          "Names": [
-# JSON_NONRELOC-NEXT:            "main"
-# JSON_NONRELOC-NEXT:          ],
-# JSON_NONRELOC-NEXT:          "Address": 6080,
-# JSON_NONRELOC-NEXT:          "Version": 0,
-# JSON_NONRELOC-NEXT:          "IsIndirectTarget": true,
-# JSON_NONRELOC-NEXT:          "TypeId": 18043682217572872138,
-# JSON_NONRELOC-NEXT:          "NumDirectCallees": 3,
-# JSON_NONRELOC-NEXT:          "DirectCallees": [
-# JSON_NONRELOC-NEXT:            {
-# JSON_NONRELOC-NEXT:              "Names": [
-# JSON_NONRELOC-NEXT:                "foo"
-# JSON_NONRELOC-NEXT:              ],
-# JSON_NONRELOC-NEXT:              "Address": 6032
-# JSON_NONRELOC-NEXT:            },
-# JSON_NONRELOC-NEXT:            {
-# JSON_NONRELOC-NEXT:              "Names": [
-# JSON_NONRELOC-NEXT:                "bar"
-# JSON_NONRELOC-NEXT:              ],
-# JSON_NONRELOC-NEXT:              "Address": 6048
-# JSON_NONRELOC-NEXT:            },
-# JSON_NONRELOC-NEXT:            {
-# JSON_NONRELOC-NEXT:              "Names": [
-# JSON_NONRELOC-NEXT:                "baz"
-# JSON_NONRELOC-NEXT:              ],
-# JSON_NONRELOC-NEXT:              "Address": 6064
-# JSON_NONRELOC-NEXT:            }
-# JSON_NONRELOC-NEXT:          ],
-# JSON_NONRELOC-NEXT:          "NumIndirectTargetTypeIDs": 2,
-# JSON_NONRELOC-NEXT:          "IndirectTypeIDs": [
-# JSON_NONRELOC-NEXT:            4524972987496481828,
-# JSON_NONRELOC-NEXT:            3498816979441845844
-# JSON_NONRELOC-NEXT:          ]
-# JSON_NONRELOC-NEXT:        }
-# JSON_NONRELOC-NEXT:      }
-# JSON_NONRELOC-NEXT:    ]
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_DYN
-  Machine:  EM_X86_64
-Sections:
-  - Name:   .text
-    Type:   SHT_PROGBITS
-    Flags:  [ SHF_ALLOC, SHF_EXECINSTR ]
-    Size:   0x2000
-  - Name:   .llvm.callgraph
-    Type:   SHT_LLVM_CALL_GRAPH
-    Flags:  [ SHF_LINK_ORDER ]
-    Link:   .text
-    ContentArray: [
-      # --- foo ---
-      0x00, # Version
-      0x01, # Flags
-      0x90, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # FunctionEntryPC: 0x1790
-      0x24, 0x44, 0xF7, 0x31, 0xF5, 0xEE, 0xCB, 0x3E, # FunctionTypeID: 0x3ECBEEF531F74424
-
-      # --- bar ---
-      0x00, # Version
-      0x01, # Flags
-      0xA0, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # FunctionEntryPC: 0x17A0
-      0x24, 0x44, 0xF7, 0x31, 0xF5, 0xEE, 0xCB, 0x3E, # FunctionTypeID: 0x3ECBEEF531F74424
-
-      # --- baz ---
-      0x00, # Version
-      0x01, # Flags
-      0xB0, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # FunctionEntryPC: 0x17B0
-      0x54, 0x86, 0xBC, 0x59, 0x81, 0x4B, 0x8E, 0x30, # FunctionTypeID: 0x308E4B8159BC8654
-
-      # --- main ---
-      0x00, # Version
-      0x07, # Flags
-      0xC0, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # FunctionEntryPC: 0x17C0
-      0xCA, 0xAF, 0x76, 0x9A, 0x60, 0x09, 0x68, 0xFA, # FunctionTypeID: 0xFA6809609A76AFCA
-
-      # Direct Callees
-      0x03, # NumDirectCallees
-      0x90, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Callee 1: 0x1790 (foo)
-      0xA0, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Callee 2: 0x17A0 (bar)
-      0xB0, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Callee 3: 0x17B0 (baz)
-
-      # Indirect Callees
-      0x02, # NumIndirectTargetTypeIDs
-      0x24, 0x44, 0xF7, 0x31, 0xF5, 0xEE, 0xCB, 0x3E, # TypeID 1
-      0x54, 0x86, 0xBC, 0x59, 0x81, 0x4B, 0x8E, 0x30  # TypeID 2
-    ]
-Symbols:
-  - Name:     foo
-    Type:     STT_FUNC
-    Section:  .text
-    Value:    0x1790
-  - Name:     bar
-    Type:     STT_FUNC
-    Section:  .text
-    Value:    0x17A0
-  - Name:     baz
-    Type:     STT_FUNC
-    Section:  .text
-    Value:    0x17B0
-  - Name:     main
-    Type:     STT_FUNC
-    Section:  .text
-    Value:    0x17C0
-...
-
-## Check relocatable object file handling.
-# RUN: yaml2obj --docnum=2 %s -o %t2
-# RUN: llvm-readelf --call-graph-info %t2 2>&1 | FileCheck %s --match-full-lines --allow-empty -check-prefix=GNU_RELOC -DFILE=%t2
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t2 2>&1 | FileCheck %s --match-full-lines --check-prefix=LLVM_RELOC -DFILE=%t2
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t2 2>&1 | FileCheck %s --match-full-lines --check-prefix=JSON_RELOC -DFILE=%t2
-
-## We do not support GNU format console output for --call-graph-info as it is an LLVM only info.
-# GNU_RELOC-NOT: .
-
-# LLVM_RELOC:   CallGraph [
-# LLVM_RELOC-NEXT:   Function {
-# LLVM_RELOC-NEXT:     Name: foo
-# LLVM_RELOC-NEXT:     Version: 0
-# LLVM_RELOC-NEXT:     IsIndirectTarget: Yes
-# LLVM_RELOC-NEXT:     TypeId: 0xF85C699BB8EF20A2
-# LLVM_RELOC-NEXT:     NumDirectCallees: 0
-# LLVM_RELOC-NEXT:     DirectCallees [
-# LLVM_RELOC-NEXT:     ]
-# LLVM_RELOC-NEXT:     NumIndirectTargetTypeIDs: 0
-# LLVM_RELOC-NEXT:     IndirectTypeIDs: []
-# LLVM_RELOC-NEXT:   }
-# LLVM_RELOC-NEXT:   Function {
-# LLVM_RELOC-NEXT:     Name: bar
-# LLVM_RELOC-NEXT:     Version: 0
-# LLVM_RELOC-NEXT:     IsIndirectTarget: Yes
-# LLVM_RELOC-NEXT:     TypeId: 0xF85C699BB8EF20A2
-# LLVM_RELOC-NEXT:     NumDirectCallees: 0
-# LLVM_RELOC-NEXT:     DirectCallees [
-# LLVM_RELOC-NEXT:     ]
-# LLVM_RELOC-NEXT:     NumIndirectTargetTypeIDs: 0
-# LLVM_RELOC-NEXT:     IndirectTypeIDs: []
-# LLVM_RELOC-NEXT:   }
-# LLVM_RELOC-NEXT:   Function {
-# LLVM_RELOC-NEXT:     Name: baz
-# LLVM_RELOC-NEXT:     Version: 0
-# LLVM_RELOC-NEXT:     IsIndirectTarget: Yes
-# LLVM_RELOC-NEXT:     TypeId: 0x308E4B8159BC8654
-# LLVM_RELOC-NEXT:     NumDirectCallees: 0
-# LLVM_RELOC-NEXT:     DirectCallees [
-# LLVM_RELOC-NEXT:     ]
-# LLVM_RELOC-NEXT:     NumIndirectTargetTypeIDs: 0
-# LLVM_RELOC-NEXT:     IndirectTypeIDs: []
-# LLVM_RELOC-NEXT:   }
-# LLVM_RELOC-NEXT:   Function {
-# LLVM_RELOC-NEXT:     Name: caller
-# LLVM_RELOC-NEXT:     Version: 0
-# LLVM_RELOC-NEXT:     IsIndirectTarget: Yes
-# LLVM_RELOC-NEXT:     TypeId: 0xA9494DEF81A01DC
-# LLVM_RELOC-NEXT:     NumDirectCallees: 3
-# LLVM_RELOC-NEXT:     DirectCallees [
-# LLVM_RELOC-NEXT:       {
-# LLVM_RELOC-NEXT:         Name: foo
-# LLVM_RELOC-NEXT:       }
-# LLVM_RELOC-NEXT:       {
-# LLVM_RELOC-NEXT:         Name: bar
-# LLVM_RELOC-NEXT:       }
-# LLVM_RELOC-NEXT:       {
-# LLVM_RELOC-NEXT:         Name: baz
-# LLVM_RELOC-NEXT:       }
-# LLVM_RELOC-NEXT:     ]
-# LLVM_RELOC-NEXT:     NumIndirectTargetTypeIDs: 2
-# LLVM_RELOC-NEXT:     IndirectTypeIDs: [0xF85C699BB8EF20A2, 0x308E4B8159BC8654]
-# LLVM_RELOC-NEXT:   }
-# LLVM_RELOC-NEXT: ]
-
-# JSON_RELOC:     "CallGraph": [
-# JSON_RELOC-NEXT:      {
-# JSON_RELOC-NEXT:        "Function": {
-# JSON_RELOC-NEXT:          "Name": "foo",
-# JSON_RELOC-NEXT:          "Version": 0,
-# JSON_RELOC-NEXT:          "IsIndirectTarget": true,
-# JSON_RELOC-NEXT:          "TypeId": 17896295136807035042,
-# JSON_RELOC-NEXT:          "NumDirectCallees": 0,
-# JSON_RELOC-NEXT:          "DirectCallees": [],
-# JSON_RELOC-NEXT:          "NumIndirectTargetTypeIDs": 0,
-# JSON_RELOC-NEXT:          "IndirectTypeIDs": []
-# JSON_RELOC-NEXT:        }
-# JSON_RELOC-NEXT:      },
-# JSON_RELOC-NEXT:      {
-# JSON_RELOC-NEXT:        "Function": {
-# JSON_RELOC-NEXT:          "Name": "bar",
-# JSON_RELOC-NEXT:          "Version": 0,
-# JSON_RELOC-NEXT:          "IsIndirectTarget": true,
-# JSON_RELOC-NEXT:          "TypeId": 17896295136807035042,
-# JSON_RELOC-NEXT:          "NumDirectCallees": 0,
-# JSON_RELOC-NEXT:          "DirectCallees": [],
-# JSON_RELOC-NEXT:          "NumIndirectTargetTypeIDs": 0,
-# JSON_RELOC-NEXT:          "IndirectTypeIDs": []
-# JSON_RELOC-NEXT:        }
-# JSON_RELOC-NEXT:      },
-# JSON_RELOC-NEXT:      {
-# JSON_RELOC-NEXT:        "Function": {
-# JSON_RELOC-NEXT:          "Name": "baz",
-# JSON_RELOC-NEXT:          "Version": 0,
-# JSON_RELOC-NEXT:          "IsIndirectTarget": true,
-# JSON_RELOC-NEXT:          "TypeId": 3498816979441845844,
-# JSON_RELOC-NEXT:          "NumDirectCallees": 0,
-# JSON_RELOC-NEXT:          "DirectCallees": [],
-# JSON_RELOC-NEXT:          "NumIndirectTargetTypeIDs": 0,
-# JSON_RELOC-NEXT:          "IndirectTypeIDs": []
-# JSON_RELOC-NEXT:        }
-# JSON_RELOC-NEXT:      },
-# JSON_RELOC-NEXT:      {
-# JSON_RELOC-NEXT:        "Function": {
-# JSON_RELOC-NEXT:          "Name": "caller",
-# JSON_RELOC-NEXT:          "Version": 0,
-# JSON_RELOC-NEXT:          "IsIndirectTarget": true,
-# JSON_RELOC-NEXT:          "TypeId": 762397922298560988,
-# JSON_RELOC-NEXT:          "NumDirectCallees": 3,
-# JSON_RELOC-NEXT:          "DirectCallees": [
-# JSON_RELOC-NEXT:            {
-# JSON_RELOC-NEXT:              "Name": "foo"
-# JSON_RELOC-NEXT:            },
-# JSON_RELOC-NEXT:            {
-# JSON_RELOC-NEXT:              "Name": "bar"
-# JSON_RELOC-NEXT:            },
-# JSON_RELOC-NEXT:            {
-# JSON_RELOC-NEXT:              "Name": "baz"
-# JSON_RELOC-NEXT:            }
-# JSON_RELOC-NEXT:          ],
-# JSON_RELOC-NEXT:          "NumIndirectTargetTypeIDs": 2,
-# JSON_RELOC-NEXT:          "IndirectTypeIDs": [
-# JSON_RELOC-NEXT:            17896295136807035042,
-# JSON_RELOC-NEXT:            3498816979441845844
-# JSON_RELOC-NEXT:          ]
-# JSON_RELOC-NEXT:        }
-# JSON_RELOC-NEXT:      }
-# JSON_RELOC-NEXT:    ]
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_REL
-  Machine:  EM_X86_64
-Sections:
-  - Name:   .text
-    Type:   SHT_PROGBITS
-    Size:   0x84
-  - Name:   .llvm.callgraph
-    Type:   SHT_LLVM_CALL_GRAPH
-    Flags:  [ SHF_LINK_ORDER ]
-    Link:   .text
-    ContentArray: [
-      # --- Entry 1: foo (foo) ---
-      # Offset 0x0
-      0x00, # Format Version
-      0x01, # Flags
-      # Offset 0x2 (Matches Reloc: foo)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Address of foo
-      0xA2, 0x20, 0xEF, 0xB8, 0x9B, 0x69, 0x5C, 0xF8, # TypeID of foo
-
-      # --- Entry 2: bar (bar) ---
-      # Offset 0x12
-      0x00, # Format Version
-      0x01, # Flags
-      # Offset 0x14 (Matches Reloc: bar)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Address of bar
-      0xA2, 0x20, 0xEF, 0xB8, 0x9B, 0x69, 0x5C, 0xF8, # TypeID of bar
-
-      # --- Entry 3: baz (baz) ---
-      # Offset 0x24
-      0x00, # Format Version
-      0x01, # Flags
-      # Offset 0x26 (Matches Reloc: baz)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Address of baz
-      0x54, 0x86, 0xBC, 0x59, 0x81, 0x4B, 0x8E, 0x30, # TypeID of baz
-
-      # --- Entry 4: caller (caller) ---
-      # Offset 0x36
-      0x00, # Format Version
-      0x07, # Flags (HasDirectCallees | IsIndirectTarget | ...)
-      # Offset 0x38 (Matches Reloc: caller)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Address of caller
-      0xDC, 0x01, 0x1A, 0xF8, 0xDE, 0x94, 0x94, 0x0A, # TypeID of caller
-
-      # Direct Callees List
-      0x03, # NumDirectCallees (3)
-      # Offset 0x49 (Matches Reloc: foo)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Callee 1: foo
-      # Offset 0x51 (Matches Reloc: bar)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Callee 2: bar
-      # Offset 0x59 (Matches Reloc: baz)
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Callee 3: baz
-
-      # Indirect Callees List
-      0x02, # NumIndirectTargetTypeIDs (2)
-      0xA2, 0x20, 0xEF, 0xB8, 0x9B, 0x69, 0x5C, 0xF8, # Indirect TypeID 1 (matches foo/bar)
-      0x54, 0x86, 0xBC, 0x59, 0x81, 0x4B, 0x8E, 0x30  # Indirect TypeID 2 (matches baz)
-    ]
-  - Name:   .rela.llvm.callgraph
-    Type:   SHT_RELA
-    Flags:  [ SHF_INFO_LINK ]
-    Info:   .llvm.callgraph
-    Relocations:
-      - Offset:  0x2
-        Symbol:  foo
-        Type:    R_X86_64_64
-      - Offset:  0x14
-        Symbol:  bar
-        Type:    R_X86_64_64
-      - Offset:  0x26
-        Symbol:  baz
-        Type:    R_X86_64_64
-      - Offset:  0x38
-        Symbol:  caller
-        Type:    R_X86_64_64
-      - Offset:  0x49
-        Symbol:  foo
-        Type:    R_X86_64_64
-      - Offset:  0x51
-        Symbol:  bar
-        Type:    R_X86_64_64
-      - Offset:  0x59
-        Symbol:  baz
-        Type:    R_X86_64_64
-Symbols:
-  - Name:  foo
-  - Name:  bar
-  - Name:  baz
-  - Name:  caller
-...
-
-## Check ARM 32-bit Thumb address handling.
-# RUN: yaml2obj --docnum=3 %s -o %t3
-# RUN: llvm-readelf --elf-output-style=LLVM --call-graph-info %t3 2>&1 | FileCheck %s --match-full-lines --check-prefix=LLVM_ARM_THUMB -DFILE=%t3
-# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --call-graph-info %t3 2>&1 | FileCheck %s --match-full-lines --check-prefix=JSON_ARM_THUMB -DFILE=%t3
-
-# LLVM_ARM_THUMB:      CallGraph [
-# LLVM_ARM_THUMB-NEXT:   Function {
-# LLVM_ARM_THUMB-NEXT:     Name: foo
-# LLVM_ARM_THUMB-NEXT:     Version: 0
-# LLVM_ARM_THUMB-NEXT:     IsIndirectTarget: No
-# LLVM_ARM_THUMB-NEXT:     TypeId: 0x123456789ABCDEF0
-# LLVM_ARM_THUMB-NEXT:     NumDirectCallees: 0
-# LLVM_ARM_THUMB-NEXT:     DirectCallees [
-# LLVM_ARM_THUMB-NEXT:     ]
-# LLVM_ARM_THUMB-NEXT:     NumIndirectTargetTypeIDs: 0
-# LLVM_ARM_THUMB-NEXT:     IndirectTypeIDs: []
-# LLVM_ARM_THUMB-NEXT:   }
-# LLVM_ARM_THUMB-NEXT: ]
-
-# JSON_ARM_THUMB:       "CallGraph": [
-# JSON_ARM_THUMB-NEXT:    {
-# JSON_ARM_THUMB-NEXT:      "Function": {
-# JSON_ARM_THUMB-NEXT:        "Name": "foo",
-# JSON_ARM_THUMB-NEXT:        "Version": 0,
-# JSON_ARM_THUMB-NEXT:        "IsIndirectTarget": false,
-# JSON_ARM_THUMB-NEXT:        "TypeId": 1311768467463790320,
-# JSON_ARM_THUMB-NEXT:        "NumDirectCallees": 0,
-# JSON_ARM_THUMB-NEXT:        "DirectCallees": [],
-# JSON_ARM_THUMB-NEXT:        "NumIndirectTargetTypeIDs": 0,
-# JSON_ARM_THUMB-NEXT:        "IndirectTypeIDs": []
-# JSON_ARM_THUMB-NEXT:      }
-# JSON_ARM_THUMB-NEXT:    }
-# JSON_ARM_THUMB-NEXT:  ]
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS32
-  Data:     ELFDATA2LSB
-  Type:     ET_REL
-  Machine:  EM_ARM
-Sections:
-  - Name:   .text
-    Type:   SHT_PROGBITS
-    Size:   0x100
-  - Name:   .llvm.callgraph
-    Type:   SHT_LLVM_CALL_GRAPH
-    Flags:  [ SHF_LINK_ORDER ]
-    Link:   .text
-    ContentArray: [
-      # --- foo+1 (Thumb address) ---
-      0x00, # Version
-      0x00, # Flags
-      0x01, 0x00, 0x00, 0x00, # FunctionEntryPC: 0x1 (relative to foo)
-      0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12 # FunctionTypeID: 0x123456789ABCDEF0
-    ]
-  - Name:   .rela.llvm.callgraph
-    Type:   SHT_RELA
-    Flags:  [ SHF_INFO_LINK ]
-    Info:   .llvm.callgraph
-    Relocations:
-      - Offset:  0x2 # Offset to FunctionEntryPC
-        Symbol:  foo
-        Type:    R_ARM_ABS32
-Symbols:
-  - Name:     foo
-    Type:     STT_FUNC
-    Section:  .text
-    Value:    0x0 
-...
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 7239230704678..96c4668984965 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -22,7 +22,6 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
@@ -37,6 +36,7 @@
 #include "llvm/Object/ELF.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/ELFTypes.h"
+#include "llvm/Object/Error.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Object/RelocationResolver.h"
 #include "llvm/Object/SFrameParser.h"
@@ -182,16 +182,6 @@ struct GroupSection {
   std::vector<GroupMember> Members;
 };
 
-// Per-function call graph information.
-struct FunctionCallgraphInfo {
-  uint64_t FunctionAddress;
-  uint8_t FormatVersionNumber;
-  bool IsIndirectTarget;
-  uint64_t FunctionTypeId;
-  SmallSet<uint64_t, 4> DirectCallees;
-  SmallSet<uint64_t, 4> IndirectTypeIDs;
-};
-
 namespace {
 
 struct NoteType {
@@ -451,15 +441,6 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
       const SFrameParser<ELFT::Endianness> &Parser,
       const typename SFrameParser<ELFT::Endianness>::FDERange::iterator FDE,
       ArrayRef<Relocation<ELFT>> Relocations, const Elf_Shdr *RelocSymTab);
-  // Callgraph - Main data structure to maintain per function callgraph
-  // information.
-  SmallVector<FunctionCallgraphInfo, 16> FuncCGInfos;
-
-  // Read the SHT_LLVM_CALL_GRAPH type section and process its contents to
-  // populate call graph related data structures which will be used to dump call
-  // graph info. Returns false if there is no SHT_LLVM_CALL_GRAPH type section
-  // in the input file.
-  bool processCallGraphSection(const Elf_Shdr *CGSection);
 
 private:
   mutable SmallVector<std::optional<VersionEntry>, 0> VersionMap;
@@ -758,7 +739,6 @@ template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> {
   void printVersionDefinitionSection(const Elf_Shdr *Sec) override;
   void printVersionDependencySection(const Elf_Shdr *Sec) override;
   void printCGProfile() override;
-  void printCallGraphInfo() override;
   void printBBAddrMaps(bool PrettyPGOAnalysis) override;
   void printAddrsig() override;
   void printNotes() override;
@@ -5337,158 +5317,6 @@ template <class ELFT> void GNUELFDumper<ELFT>::printCGProfile() {
   OS << "GNUStyle::printCGProfile not implemented\n";
 }
 
-namespace callgraph {
-LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
-enum Flags : uint8_t {
-  None = 0,
-  IsIndirectTarget = 1u << 0,
-  HasDirectCallees = 1u << 1,
-  HasIndirectCallees = 1u << 2,
-  LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ HasIndirectCallees)
-};
-} // namespace callgraph
-
-template <class ELFT>
-bool ELFDumper<ELFT>::processCallGraphSection(const Elf_Shdr *CGSection) {
-  Expected<ArrayRef<uint8_t>> SectionBytesOrErr =
-      Obj.getSectionContents(*CGSection);
-  if (!SectionBytesOrErr) {
-    reportWarning(
-        createError("unable to read the SHT_LLVM_CALL_GRAPH type section " +
-                    toString(SectionBytesOrErr.takeError())),
-        FileName);
-    return false;
-  }
-
-  DataExtractor Data(SectionBytesOrErr.get(), Obj.isLE(),
-                     ObjF.getBytesInAddress());
-  DataExtractor::Cursor C(0);
-  uint64_t UnknownCount = 0;
-  while (C && C.tell() < CGSection->sh_size) {
-    uint8_t FormatVersionNumber = Data.getU8(C);
-    if (!C) {
-      reportWarning(createError("failed while reading FormatVersionNumber " +
-                                toString(C.takeError())),
-                    FileName);
-      return false;
-    }
-    if (FormatVersionNumber != 0) {
-      reportWarning(createError("unknown format version value [" +
-                                std::to_string(FormatVersionNumber) +
-                                "] in SHT_LLVM_CALL_GRAPH type section"),
-                    FileName);
-      return false;
-    }
-
-    uint8_t FlagsVal = Data.getU8(C);
-    if (!C) {
-      reportWarning(
-          createError("failed while reading call graph info's Flags " +
-                      toString(C.takeError())),
-          FileName);
-      return false;
-    }
-    callgraph::Flags CGFlags = static_cast<callgraph::Flags>(FlagsVal);
-    constexpr callgraph::Flags ValidFlags = callgraph::IsIndirectTarget |
-                                            callgraph::HasDirectCallees |
-                                            callgraph::HasIndirectCallees;
-    constexpr uint8_t ValidMask = static_cast<uint8_t>(ValidFlags);
-    if ((FlagsVal & ~ValidMask) != 0) {
-      reportWarning(createError("unexpected Flags value [" +
-                                std::to_string(FlagsVal) + "] "),
-                    FileName);
-      return false;
-    }
-
-    uint64_t FuncAddrOffset = C.tell();
-    uint64_t FuncAddr =
-        static_cast<uint64_t>(Data.getUnsigned(C, sizeof(typename ELFT::uint)));
-    if (!C) {
-      reportWarning(
-          createError(
-              "failed while reading call graph info function entry PC " +
-              toString(C.takeError())),
-          FileName);
-      return false;
-    }
-
-    bool IsETREL = this->Obj.getHeader().e_type == ELF::ET_REL;
-    // Create a new entry for this function.
-    FunctionCallgraphInfo CGInfo;
-    CGInfo.FunctionAddress = IsETREL ? FuncAddrOffset : FuncAddr;
-    CGInfo.FormatVersionNumber = FormatVersionNumber;
-    bool IsIndirectTarget =
-        (CGFlags & callgraph::IsIndirectTarget) != callgraph::None;
-    CGInfo.IsIndirectTarget = IsIndirectTarget;
-    uint64_t TypeId = Data.getU64(C);
-    if (!C) {
-      reportWarning(createError("failed while reading function type ID " +
-                                toString(C.takeError())),
-                    FileName);
-      return false;
-    }
-    CGInfo.FunctionTypeId = TypeId;
-    if (IsIndirectTarget && TypeId == 0)
-      ++UnknownCount;
-
-    if (CGFlags & callgraph::HasDirectCallees) {
-      // Read number of direct call sites for this function.
-      uint64_t NumDirectCallees = Data.getULEB128(C);
-      if (!C) {
-        reportWarning(
-            createError("failed while reading number of direct callees " +
-                        toString(C.takeError())),
-            FileName);
-        return false;
-      }
-      // Read unique direct callees and populate FuncCGInfos.
-      for (uint64_t I = 0; I < NumDirectCallees; ++I) {
-        uint64_t CalleeOffset = C.tell();
-        uint64_t Callee = static_cast<uint64_t>(
-            Data.getUnsigned(C, sizeof(typename ELFT::uint)));
-        if (!C) {
-          reportWarning(createError("failed while reading direct callee " +
-                                    toString(C.takeError())),
-                        FileName);
-          return false;
-        }
-        CGInfo.DirectCallees.insert((IsETREL ? CalleeOffset : Callee));
-      }
-    }
-
-    if (CGFlags & callgraph::HasIndirectCallees) {
-      uint64_t NumIndirectTargetTypeIDs = Data.getULEB128(C);
-      if (!C) {
-        reportWarning(
-            createError(
-                "failed while reading number of indirect target type IDs " +
-                toString(C.takeError())),
-            FileName);
-        return false;
-      }
-      // Read unique indirect target type IDs and populate FuncCGInfos.
-      for (uint64_t I = 0; I < NumIndirectTargetTypeIDs; ++I) {
-        uint64_t TargetType = Data.getU64(C);
-        if (!C) {
-          reportWarning(
-              createError("failed while reading indirect target type ID " +
-                          toString(C.takeError())),
-              FileName);
-          return false;
-        }
-        CGInfo.IndirectTypeIDs.insert(TargetType);
-      }
-    }
-    FuncCGInfos.push_back(CGInfo);
-  }
-
-  if (UnknownCount)
-    reportUniqueWarning(
-        "SHT_LLVM_CALL_GRAPH type section has unknown type id for " +
-        std::to_string(UnknownCount) + " indirect targets");
-  return true;
-}
-
 template <class ELFT>
 void GNUELFDumper<ELFT>::printBBAddrMaps(bool /*PrettyPGOAnalysis*/) {
   OS << "GNUStyle::printBBAddrMaps not implemented\n";
@@ -8320,110 +8148,6 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
   }
 }
 
-template <class ELFT> void LLVMELFDumper<ELFT>::printCallGraphInfo() {
-  // Call graph section is of type SHT_LLVM_CALL_GRAPH. Typically named
-  // ".llvm.callgraph". First fetch the section by its type.
-  using Elf_Shdr = typename ELFT::Shdr;
-  Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> MapOrErr =
-      this->Obj.getSectionAndRelocations([](const Elf_Shdr &Sec) {
-        return Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH;
-      });
-  if (!MapOrErr || MapOrErr->empty()) {
-    reportWarning(createError("no SHT_LLVM_CALL_GRAPH section found " +
-                              toString(MapOrErr.takeError())),
-                  this->FileName);
-    return;
-  }
-  if (!this->processCallGraphSection(MapOrErr->begin()->first) ||
-      this->FuncCGInfos.empty())
-    return;
-
-  std::vector<Relocation<ELFT>> Relocations;
-  const Elf_Shdr *RelocSymTab = nullptr;
-  if (this->Obj.getHeader().e_type == ELF::ET_REL) {
-    const Elf_Shdr *CGRelSection = MapOrErr->front().second;
-    if (CGRelSection) {
-      this->forEachRelocationDo(
-          *CGRelSection, [&](const Relocation<ELFT> &R, unsigned Ndx,
-                             const Elf_Shdr &Sec, const Elf_Shdr *SymTab) {
-            RelocSymTab = SymTab;
-            Relocations.push_back(R);
-          });
-      llvm::stable_sort(Relocations, [](const auto &LHS, const auto &RHS) {
-        return LHS.Offset < RHS.Offset;
-      });
-    }
-  }
-
-  auto GetFunctionNames = [&](uint64_t FuncAddr) {
-    SmallVector<uint32_t> FuncSymIndexes =
-        this->getSymbolIndexesForFunctionAddress(FuncAddr, std::nullopt);
-    SmallVector<std::string> FuncSymNames;
-    FuncSymNames.reserve(FuncSymIndexes.size());
-    for (uint32_t Index : FuncSymIndexes)
-      FuncSymNames.push_back(this->getStaticSymbolName(Index));
-    return FuncSymNames;
-  };
-
-  auto PrintNonRelocatableFuncSymbol = [&](uint64_t FuncEntryPC) {
-    SmallVector<std::string> FuncSymNames = GetFunctionNames(FuncEntryPC);
-    if (!FuncSymNames.empty())
-      W.printList("Names", FuncSymNames);
-    W.printHex("Address", FuncEntryPC);
-  };
-
-  auto PrintRelocatableFuncSymbol = [&](uint64_t RelocOffset) {
-    auto R = llvm::find_if(Relocations, [&](const Relocation<ELFT> &R) {
-      return R.Offset == RelocOffset;
-    });
-    if (R == Relocations.end()) {
-      this->reportUniqueWarning("unknown relocation at offset " +
-                                Twine(RelocOffset));
-      return;
-    }
-    Expected<RelSymbol<ELFT>> RelSymOrErr =
-        this->getRelocationTarget(*R, RelocSymTab);
-    if (!RelSymOrErr) {
-      this->reportUniqueWarning(RelSymOrErr.takeError());
-      return;
-    }
-    if (!RelSymOrErr->Name.empty())
-      W.printString("Name", RelSymOrErr->Name);
-  };
-
-  auto PrintFunc = [&](uint64_t FuncPC) {
-    uint64_t FuncEntryPC = FuncPC;
-    // Clear Thumb bit if it was set before symbol lookup.
-    if (this->Obj.getHeader().e_machine == ELF::EM_ARM)
-      FuncEntryPC = FuncPC & ~1;
-    if (this->Obj.getHeader().e_type == ELF::ET_REL)
-      PrintRelocatableFuncSymbol(FuncEntryPC);
-    else
-      PrintNonRelocatableFuncSymbol(FuncEntryPC);
-  };
-
-  ListScope CGI(W, "CallGraph");
-  for (const auto &CGInfo : this->FuncCGInfos) {
-    DictScope D(W, "Function");
-    PrintFunc(CGInfo.FunctionAddress);
-    W.printNumber("Version", CGInfo.FormatVersionNumber);
-    W.printBoolean("IsIndirectTarget", CGInfo.IsIndirectTarget);
-    W.printHex("TypeId", CGInfo.FunctionTypeId);
-    W.printNumber("NumDirectCallees", CGInfo.DirectCallees.size());
-    {
-      ListScope DCs(W, "DirectCallees");
-      for (auto CalleePC : CGInfo.DirectCallees) {
-        DictScope D(W);
-        PrintFunc(CalleePC);
-      }
-    }
-    W.printNumber("NumIndirectTargetTypeIDs", CGInfo.IndirectTypeIDs.size());
-    SmallVector<uint64_t, 4> IndirectTypeIdsList(CGInfo.IndirectTypeIDs.begin(),
-                                                 CGInfo.IndirectTypeIDs.end());
-    W.printHexList("IndirectTypeIDs", ArrayRef(IndirectTypeIdsList));
-  }
-}
-
 template <class ELFT>
 void LLVMELFDumper<ELFT>::printBBAddrMaps(bool PrettyPGOAnalysis) {
   bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL;
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index 0dba8252fd466..d26439435a82b 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -130,7 +130,6 @@ class ObjDumper {
   virtual void printGroupSections() {}
   virtual void printHashHistograms() {}
   virtual void printCGProfile() {}
-  virtual void printCallGraphInfo() {}
   // If PrettyPGOAnalysis is true, prints BFI as relative frequency and BPI as
   // percentage. Otherwise raw values are displayed.
   virtual void printBBAddrMaps(bool PrettyPGOAnalysis) {}
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index f489e564d3182..97d5d7f96dc32 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -20,7 +20,6 @@ def all : FF<"all", "Equivalent to setting: --file-header, --program-headers, --
 def arch_specific : FF<"arch-specific", "Display architecture-specific information">;
 def bb_addr_map : FF<"bb-addr-map", "Display the BB address map section">;
 def pretty_pgo_analysis_map : FF<"pretty-pgo-analysis-map", "Display PGO analysis values with formatting rather than raw numbers">;
-def call_graph_info : FF<"call-graph-info", "Display call graph information">;
 def cg_profile : FF<"cg-profile", "Display call graph profile section">;
 def decompress : FF<"decompress", "Dump decompressed section content when used with -x or -p">;
 defm demangle : BB<"demangle", "Demangle symbol names", "Do not demangle symbol names (default)">;
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 95fb283940c17..5327731805010 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -99,7 +99,6 @@ static bool ArchSpecificInfo;
 static bool BBAddrMap;
 static bool PrettyPGOAnalysisMap;
 bool ExpandRelocs;
-static bool CallGraphInfo;
 static bool CGProfile;
 static bool Decompress;
 bool Demangle;
@@ -223,7 +222,6 @@ static void parseOptions(const opt::InputArgList &Args) {
     WithColor::warning(errs(), ToolName)
         << "--bb-addr-map must be enabled for --pretty-pgo-analysis-map to "
            "have an effect\n";
-  opts::CallGraphInfo = Args.hasArg(OPT_call_graph_info);
   opts::CGProfile = Args.hasArg(OPT_cg_profile);
   opts::Decompress = Args.hasArg(OPT_decompress);
   opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
@@ -480,8 +478,6 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
       Dumper->printHashHistograms();
     if (opts::CGProfile)
       Dumper->printCGProfile();
-    if (opts::CallGraphInfo)
-      Dumper->printCallGraphInfo();
     if (opts::BBAddrMap)
       Dumper->printBBAddrMaps(opts::PrettyPGOAnalysisMap);
     if (opts::Addrsig)



More information about the llvm-branch-commits mailing list