[llvm] [docs][llvm-readobj] Document the --call-graph-info output format (PR #227386)
Prabhu Rajasekaran via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 6 15:47:01 PDT 2026
https://github.com/Prabhuk updated https://github.com/llvm/llvm-project/pull/227386
>From 41e1048c7ed01fd61af07cfcff6298831b2d685f Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 29 Sep 2026 09:56:06 -0700
Subject: [PATCH 1/3] [docs][llvm-readobj] Document the --call-graph-info
output format
Describe the fields llvm-readobj prints for each call graph record, for
both executables and relocatable object files, with an example of each.
The relocatable object file format is added in #213156.
---
llvm/docs/CallGraphSection.md | 102 ++++++++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
diff --git a/llvm/docs/CallGraphSection.md b/llvm/docs/CallGraphSection.md
index 84d606162718be7..2bfa50dc39c3a24 100644
--- a/llvm/docs/CallGraphSection.md
+++ b/llvm/docs/CallGraphSection.md
@@ -16,3 +16,105 @@ Each record in the `.llvm.callgraph` section has the following binary layout:
| Direct Callees Array | `uintptr_t[]` | Variable | An array of unique direct callee entry point addresses. This field is only present if there is at least one direct callee. |
| Number of Unique Indirect Target Type IDs| `ULEB128` | Variable | The number of unique indirect call target type IDs. This field is only present if there is at least one indirect target type ID. |
| Indirect Target Type IDs Array | `uint64_t[]` | Variable | An array of unique indirect call target type IDs. This field is only present if there is at least one indirect target type ID. |
+
+## Dumping with llvm-readobj
+
+`llvm-readobj --call-graph-info` prints the records of every `SHT_LLVM_CALL_GRAPH` section in a file. With `--elf-output-style=JSON`, the output is a `CallGraph` array that holds one `Function` object per record. The default `LLVM` output style prints the same fields, with addresses and type IDs in hexadecimal.
+
+In executables and shared objects, functions are identified by their addresses. In relocatable object files the address fields are not final, so each function is identified by the relocation that applies to its address field instead.
+
+### Function Object
+
+| Field | Type | Description |
+| -------------------------- | ---------------- | ----------- |
+| `Names` | array of strings | The names of the function symbols at `Address`. Omitted if there are none. Executables and shared objects only. |
+| `Address` | integer | The function entry address. On ARM, the Thumb bit is cleared. Executables and shared objects only. |
+| `Reloc` | object | The relocation that applies to the function entry PC field. See below. Relocatable object files only. |
+| `Offset` | integer | The offset of the function entry PC field within the section. Printed instead of `Reloc` when the relocation cannot be determined. Relocatable object files only. |
+| `Version` | integer | The format version. |
+| `IsIndirectTarget` | boolean | Whether the function is a potential indirect call target. |
+| `TypeID` | integer | The function type ID. |
+| `NumDirectCallees` | integer | The number of entries in `DirectCallees`. |
+| `DirectCallees` | array of objects | One object per direct callee, identified the same way as the function: by `Names` and `Address`, or by `Reloc` or `Offset`. In executables and shared objects, each callee address is listed once. |
+| `NumIndirectTargetTypeIDs` | integer | The number of entries in `IndirectTypeIDs`. |
+| `IndirectTypeIDs` | array of integers | The indirect call target type IDs. |
+
+### Reloc Object
+
+| Field | Type | Description |
+| ------------- | ------- | ----------- |
+| `SymbolIndex` | integer | The symbol table index of the relocation's symbol, or 0 if it has none. |
+| `SymbolName` | string | The name that the symbol's `st_name` refers to, demangled if `--demangle` is given. Omitted if the symbol has no name, such as an `STT_SECTION` symbol. |
+| `Addend` | integer | The relocation addend. For relocations without an explicit addend, such as `SHT_REL` relocations, this is the value stored in the field. Omitted if zero. |
+
+### Examples
+
+A function in a shared object that calls `foo` and `bar`:
+
+```json
+"CallGraph": [
+ {
+ "Function": {
+ "Names": [
+ "main"
+ ],
+ "Address": 6080,
+ "Version": 0,
+ "IsIndirectTarget": false,
+ "TypeID": 0,
+ "NumDirectCallees": 2,
+ "DirectCallees": [
+ {
+ "Names": [
+ "foo"
+ ],
+ "Address": 6032
+ },
+ {
+ "Names": [
+ "bar"
+ ],
+ "Address": 6048
+ }
+ ],
+ "NumIndirectTargetTypeIDs": 0,
+ "IndirectTypeIDs": []
+ }
+ }
+]
+```
+
+A function in a relocatable object file that calls two local functions. The callees are referenced through the section symbol, so they have no `SymbolName`, and the addends give their offsets within the section:
+
+```json
+"CallGraph": [
+ {
+ "Function": {
+ "Reloc": {
+ "SymbolIndex": 3,
+ "SymbolName": "caller"
+ },
+ "Version": 0,
+ "IsIndirectTarget": true,
+ "TypeID": 9080559750644022485,
+ "NumDirectCallees": 2,
+ "DirectCallees": [
+ {
+ "Reloc": {
+ "SymbolIndex": 1,
+ "Addend": 16
+ }
+ },
+ {
+ "Reloc": {
+ "SymbolIndex": 1,
+ "Addend": 24
+ }
+ }
+ ],
+ "NumIndirectTargetTypeIDs": 0,
+ "IndirectTypeIDs": []
+ }
+ }
+]
+```
>From bbe7e69940b34deea659647eee93b9a3affb54b3 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 6 Oct 2026 15:40:23 -0700
Subject: [PATCH 2/3] Address review feedback on the call graph output docs
---
llvm/docs/CallGraphSection.md | 67 +++++++++++++++++++++++++----------
1 file changed, 49 insertions(+), 18 deletions(-)
diff --git a/llvm/docs/CallGraphSection.md b/llvm/docs/CallGraphSection.md
index 2bfa50dc39c3a24..fe1f5cb9c354e17 100644
--- a/llvm/docs/CallGraphSection.md
+++ b/llvm/docs/CallGraphSection.md
@@ -21,30 +21,30 @@ Each record in the `.llvm.callgraph` section has the following binary layout:
`llvm-readobj --call-graph-info` prints the records of every `SHT_LLVM_CALL_GRAPH` section in a file. With `--elf-output-style=JSON`, the output is a `CallGraph` array that holds one `Function` object per record. The default `LLVM` output style prints the same fields, with addresses and type IDs in hexadecimal.
-In executables and shared objects, functions are identified by their addresses. In relocatable object files the address fields are not final, so each function is identified by the relocation that applies to its address field instead.
+Each function and direct callee is identified by exactly one of `Address` or `Relocation`. If a relocation applies to its address field, as in relocatable object files, `Relocation` describes that relocation. Otherwise, `Address` holds the value stored in the field. Either one may be accompanied by `Names`, the symbolization of that address for human readers.
### Function Object
| Field | Type | Description |
| -------------------------- | ---------------- | ----------- |
-| `Names` | array of strings | The names of the function symbols at `Address`. Omitted if there are none. Executables and shared objects only. |
-| `Address` | integer | The function entry address. On ARM, the Thumb bit is cleared. Executables and shared objects only. |
-| `Reloc` | object | The relocation that applies to the function entry PC field. See below. Relocatable object files only. |
-| `Offset` | integer | The offset of the function entry PC field within the section. Printed instead of `Reloc` when the relocation cannot be determined. Relocatable object files only. |
+| `Names` | array of strings | The symbolization of the function's entry address, similar to what `llvm-symbolizer` shows: the names of the function symbols defined at that address. When `Relocation` is present, the address is where the relocation points: the symbol's value plus the addend, within the symbol's section. For human readers only, so it can differ from the relocation's `SymbolName`, for example when the relocation uses a section symbol. Omitted if there are none, for example when the relocation's symbol is undefined. |
+| `Address` | integer | The value stored in the function entry PC field, which in executables and shared objects is the function's entry address. On ARM, the Thumb bit is cleared. Printed when no relocation applies to the field. |
+| `Relocation` | object | The relocation that applies to the function entry PC field. See below. Printed instead of `Address`. |
| `Version` | integer | The format version. |
| `IsIndirectTarget` | boolean | Whether the function is a potential indirect call target. |
| `TypeID` | integer | The function type ID. |
| `NumDirectCallees` | integer | The number of entries in `DirectCallees`. |
-| `DirectCallees` | array of objects | One object per direct callee, identified the same way as the function: by `Names` and `Address`, or by `Reloc` or `Offset`. In executables and shared objects, each callee address is listed once. |
+| `DirectCallees` | array of objects | One object per direct callee, with the same `Names`, `Address` and `Relocation` fields as the function. Callees identified by `Address` are listed once per address. |
| `NumIndirectTargetTypeIDs` | integer | The number of entries in `IndirectTypeIDs`. |
| `IndirectTypeIDs` | array of integers | The indirect call target type IDs. |
-### Reloc Object
+### Relocation Object
| Field | Type | Description |
| ------------- | ------- | ----------- |
+| `Type` | object | The relocation type, with its `Name` (such as `R_X86_64_64`) and numeric `Value`. |
| `SymbolIndex` | integer | The symbol table index of the relocation's symbol, or 0 if it has none. |
-| `SymbolName` | string | The name that the symbol's `st_name` refers to, demangled if `--demangle` is given. Omitted if the symbol has no name, such as an `STT_SECTION` symbol. |
+| `SymbolName` | string | The symbol's name exactly as given by `st_name`. Omitted if the symbol has no name, such as an `STT_SECTION` symbol. |
| `Addend` | integer | The relocation addend. For relocations without an explicit addend, such as `SHT_REL` relocations, this is the value stored in the field. Omitted if zero. |
### Examples
@@ -84,31 +84,62 @@ A function in a shared object that calls `foo` and `bar`:
]
```
-A function in a relocatable object file that calls two local functions. The callees are referenced through the section symbol, so they have no `SymbolName`, and the addends give their offsets within the section:
+A function in a relocatable object file that calls a local function `foo`, a global function `bar` and an undefined function `ext`. The relocation for `foo` uses the `.text` section symbol, which has no name, so it has no `SymbolName`, but `Names` still shows `foo`. `ext` is not defined in the file, so it has no `Names`:
```json
"CallGraph": [
{
"Function": {
- "Reloc": {
- "SymbolIndex": 3,
+ "Names": [
+ "caller"
+ ],
+ "Relocation": {
+ "Type": {
+ "Name": "R_X86_64_64",
+ "Value": 1
+ },
+ "SymbolIndex": 6,
"SymbolName": "caller"
},
"Version": 0,
"IsIndirectTarget": true,
"TypeID": 9080559750644022485,
- "NumDirectCallees": 2,
+ "NumDirectCallees": 3,
"DirectCallees": [
{
- "Reloc": {
- "SymbolIndex": 1,
- "Addend": 16
+ "Names": [
+ "foo"
+ ],
+ "Relocation": {
+ "Type": {
+ "Name": "R_X86_64_64",
+ "Value": 1
+ },
+ "SymbolIndex": 2,
+ "Addend": 48
+ }
+ },
+ {
+ "Names": [
+ "bar"
+ ],
+ "Relocation": {
+ "Type": {
+ "Name": "R_X86_64_64",
+ "Value": 1
+ },
+ "SymbolIndex": 4,
+ "SymbolName": "bar"
}
},
{
- "Reloc": {
- "SymbolIndex": 1,
- "Addend": 24
+ "Relocation": {
+ "Type": {
+ "Name": "R_X86_64_64",
+ "Value": 1
+ },
+ "SymbolIndex": 7,
+ "SymbolName": "ext"
}
}
],
>From d03d0fb5553b2678267ccb5975b240116f927294 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 6 Oct 2026 15:46:42 -0700
Subject: [PATCH 3/3] Drop the redundant callee and type ID counts from the
docs
---
llvm/docs/CallGraphSection.md | 6 ------
1 file changed, 6 deletions(-)
diff --git a/llvm/docs/CallGraphSection.md b/llvm/docs/CallGraphSection.md
index fe1f5cb9c354e17..9340bbd61bdd34b 100644
--- a/llvm/docs/CallGraphSection.md
+++ b/llvm/docs/CallGraphSection.md
@@ -33,9 +33,7 @@ Each function and direct callee is identified by exactly one of `Address` or `Re
| `Version` | integer | The format version. |
| `IsIndirectTarget` | boolean | Whether the function is a potential indirect call target. |
| `TypeID` | integer | The function type ID. |
-| `NumDirectCallees` | integer | The number of entries in `DirectCallees`. |
| `DirectCallees` | array of objects | One object per direct callee, with the same `Names`, `Address` and `Relocation` fields as the function. Callees identified by `Address` are listed once per address. |
-| `NumIndirectTargetTypeIDs` | integer | The number of entries in `IndirectTypeIDs`. |
| `IndirectTypeIDs` | array of integers | The indirect call target type IDs. |
### Relocation Object
@@ -62,7 +60,6 @@ A function in a shared object that calls `foo` and `bar`:
"Version": 0,
"IsIndirectTarget": false,
"TypeID": 0,
- "NumDirectCallees": 2,
"DirectCallees": [
{
"Names": [
@@ -77,7 +74,6 @@ A function in a shared object that calls `foo` and `bar`:
"Address": 6048
}
],
- "NumIndirectTargetTypeIDs": 0,
"IndirectTypeIDs": []
}
}
@@ -104,7 +100,6 @@ A function in a relocatable object file that calls a local function `foo`, a glo
"Version": 0,
"IsIndirectTarget": true,
"TypeID": 9080559750644022485,
- "NumDirectCallees": 3,
"DirectCallees": [
{
"Names": [
@@ -143,7 +138,6 @@ A function in a relocatable object file that calls a local function `foo`, a glo
}
}
],
- "NumIndirectTargetTypeIDs": 0,
"IndirectTypeIDs": []
}
}
More information about the llvm-commits
mailing list