LLVM-SYMBOLIZER(1)
π NAME π
llvm-symbolizer β bestie, it converts addresses into source code locations. That's the whole vibe. π
β¨ SYNOPSIS β¨
llvm-symbolizer [options] [addressesβ¦]
π¦ DESCRIPTION π¦
Okay so here's the tea, bestie: llvm-symbolizer reads input names and addresses straight off the command line and prints the matching source code locations to standard output. It can also symbolize logs that contain Symbolizer Markup, but only if you hit it with --filter-markup. Lowkey iconic. β¨
If you don't hand it any address on the command line, it just reads the addresses from standard input instead. And if you didn't give it an input name on the command line but you did give it addresses β or honestly if at any point it just doesn't recognize an input value β it simply echoes that input to the output. No drama, no cap. π«Ά
Input names can come along with the addresses, either on standard input or as positional arguments on the command line. By default, input names get interpreted as object file paths. But here's the glow-up: if you prefix a name with BUILDID:, that says "hey this is a hex build ID, not a path," and it'll go look up the corresponding debug binary for you. And for consistency, prefixing a name with FILE: explicitly states that it's an object file path β which is literally the default anyway. π
A positional argument or standard input value can also be preceded by DATA or CODE to say whether that address should be symbolized as data or as executable code. If you don't specify either one, CODE is just assumed, ngl. And heads up: DATA gets symbolized as address and symbol size rather than line number. π
Also! llvm-symbolizer parses options from the environment variable LLVM_SYMBOLIZER_OPTS after it parses options from the command line. This is mainly useful for supplementing the command-line options when llvm-symbolizer is being invoked by another program or runtime. iykyk. πΈ
π₯ EXAMPLES π₯
Every single example below uses these two source files as input. They mix C-style and C++-style linkage on purpose, to show how those names get printed differently β peep --demangle for that. π
// test.h
extern "C" inline int foz() {
return 1234;
}
// test.cpp
#include "test.h"
int bar=42;
int foo() {
return bar;
}
int baz() {
volatile int k = 42;
return foz() + k;
}
int main() {
return foo() + baz();
}
And these files get built like this:
$ clang -g test.cpp -o test.elf
$ clang -g -O2 test.cpp -o inlined.elf
π Example 1 β addresses and object on command-line
$ llvm-symbolizer --obj=test.elf 0x4004d0 0x400490
foz
/tmp/test.h:1:0
baz()
/tmp/test.cpp:11:0
π Example 2 β addresses on standard input
$ cat addr.txt
0x4004a0
0x400490
0x4004d0
$ llvm-symbolizer --obj=test.elf < addr.txt
main
/tmp/test.cpp:15:0
baz()
/tmp/test.cpp:11:0
foz
/tmp/./test.h:1:0
π Example 3 β object specified with address
$ llvm-symbolizer "test.elf 0x400490" "FILE:inlined.elf 0x400480"
baz()
/tmp/test.cpp:11:0
foo()
/tmp/test.cpp:8:10
$ cat addr2.txt
FILE:test.elf 0x4004a0
inlined.elf 0x400480
$ llvm-symbolizer < addr2.txt
main
/tmp/test.cpp:15:0
foo()
/tmp/test.cpp:8:10
π Example 4 β BUILDID and FILE prefixes
$ llvm-symbolizer "FILE:test.elf 0x400490" "DATA BUILDID:123456789abcdef 0x601028"
baz()
/tmp/test.cpp:11:0
bar
6295592 4
$ cat addr3.txt
FILE:test.elf 0x400490
DATA BUILDID:123456789abcdef 0x601028
$ llvm-symbolizer < addr3.txt
baz()
/tmp/test.cpp:11:0
bar
6295592 4
π Example 5 β CODE and DATA prefixes
$ llvm-symbolizer --obj=test.elf "CODE 0x400490" "DATA 0x601028"
baz()
/tmp/test.cpp:11:0
bar
6295592 4
$ cat addr4.txt
CODE test.elf 0x4004a0
DATA inlined.elf 0x601028
$ llvm-symbolizer < addr4.txt
main
/tmp/test.cpp:15:0
bar
6295592 4
π Example 6 β path-style options
This one uses the same source file as above, but the source file's full path is /tmp/foo/test.cpp, and it gets compiled like so. The first case shows the default absolute path, the second shows --basenames, and the third shows --relativenames. β¨
$ pwd
/tmp
$ clang -g foo/test.cpp -o test.elf
$ llvm-symbolizer --obj=test.elf 0x4004a0
main
/tmp/foo/test.cpp:15:0
$ llvm-symbolizer --obj=test.elf 0x4004a0 --basenames
main
test.cpp:15:0
$ llvm-symbolizer --obj=test.elf 0x4004a0 --relativenames
main
foo/test.cpp:15:0
π OPTIONS π
okay bestie, buckle UP, this is the flag menu and it is long. every single one of them is here, no skips, no shortcuts, i promise. π
--adjust-vma <offset>β adds that offset to object file addresses while it's doing lookups. so it's basically "pretend the object got relocated by this much" energy. β¨--basenames,-sβ prints just the file's name, no directories, instead of the full absolute path. short and sweet, lowkey iconic. π--build-idβ looks up the object using the build ID you give it, written as a hex string. mutually exclusive with--obj, so pick a lane bestie, you can't have both. π--color [=<always|auto|never>]β tells it whether to use color in--filter-markupmode. defaults toauto, which sniffs out whether standard output can even do color. and if you just write--colorwith nothing else? that's the same as--color=always. slay. π¦--debug-file-directory <path>β hands it a path to a directory that has a.build-idsubdirectory, so it can go hunting for debug info for stripped binaries. pass this more than once and it searches them in the order given. π§--debuginfod,--no-debuginfodβ whether to try debuginfod lookups for debug binaries or not. unless you say otherwise, debuginfod is only on if libcurl was compiled in (LLVM_ENABLE_CURL) and at least one server URL came from the environment variableDEBUGINFOD_URLS. πΈ--demangle,-Cβ prints demangled function names when the names are mangled. like the mangled name_Z3bazvturns intobaz(), but the already-non-mangledfozjust gets printed as it is. defaults to true. π--dwp <path>β use the DWP file sitting at<path>for any CUs that have split DWARF debug data.--fallback-debug-path <path>β when a separate file holds the debug data and it's referenced by a GNU debug link section, use this path as the base for finding that debug data if it can't be found relative to the object. the backup plan, fr fr. π«Ά--filter-markupβ reads from standard input, turns the Symbolizer Markup it finds into human-readable form, and prints the results to standard output. these markup elements are not yet supported, so don't come for me:{{{hexdict}}}{{{dumpfile}}}
the {{{bt}}} backtrace element reports frames with this syntax:
#<number>[.<inline>] <address> <function> <file>:<line>:<col>
(<module>+<relative address>)
<inline> gives you the frame numbers for calls inlined into the caller corresponding to <number>. those inlined call numbers start at 1 and go up from callee to caller. <address> is an address inside the call instruction to the function β and heads up, it might not be the start of that instruction. <relative address> is the matching virtual offset in the <module> loaded at that address. π (so much detail, but you asked)
--functions [=<none|short|linkage>],-fβ picks how function names get printed: no function name at all, short function name, or the full linkage name. defaults tolinkage. π--help,-hβ shows help and usage for this command. the classic.--inlining,--inlines,-iβ if a source code location is inside an inlined function, it prints all the inlined frames. this is the default, bestie. π--no-inlinesβ doesn't print inlined frames. the opposite vibe.--no-demangleβ doesn't print demangled function names.--obj <path>,--exe,-eβ path to the object file you want symbolized. if you pass-, it reads the object straight from the standard input stream. mutually exclusive with--build-id. π₯--output-style <LLVM|GNU|JSON>β sets the preferred output style, defaults toLLVM. when it'sGNU, the tool follows GNU'saddr2linestyle. the differences from LLVM style are:- it does not print the column of a source code location.
- it does not add an empty line after the report for an address.
- it does not replace the name of an inlined function with the name of the topmost caller when inlined frames aren't shown.
- it prints an address's debug-data discriminator when it's non-zero. one way to produce discriminators is compiling with clang's
-fdebug-info-for-profiling.
JSON style gives you machine readable output in JSON. if addresses are supplied via stdin, the output JSON will be a series of individual objects. otherwise, all results will be contained in a single array. π
$ llvm-symbolizer --obj=inlined.elf 0x4004be 0x400486 -p
baz() at /tmp/test.cpp:11:18
(inlined by) main at /tmp/test.cpp:15:0
foo() at /tmp/test.cpp:6:3
$ llvm-symbolizer --output-style=LLVM --obj=inlined.elf 0x4004be 0x400486 -p --no-inlines
main at /tmp/test.cpp:11:18
foo() at /tmp/test.cpp:6:3
$ llvm-symbolizer --output-style=GNU --obj=inlined.elf 0x4004be 0x400486 -p --no-inlines
baz() at /tmp/test.cpp:11
foo() at /tmp/test.cpp:6
$ clang -g -fdebug-info-for-profiling test.cpp -o profiling.elf
$ llvm-symbolizer --output-style=GNU --obj=profiling.elf 0x401167 -p --no-inlines
main at /tmp/test.cpp:15 (discriminator 2)
$ llvm-symbolizer --output-style=JSON --obj=inlined.elf 0x4004be 0x400486 -p
[
{
"Address": "0x4004be",
"ModuleName": "inlined.elf",
"Symbol": [
{
"Column": 18,
"Discriminator": 0,
"FileName": "/tmp/test.cpp",
"FunctionName": "baz()",
"Line": 11,
"StartAddress": "0x4004be",
"StartFileName": "/tmp/test.cpp",
"StartLine": 9
},
{
"Column": 0,
"Discriminator": 0,
"FileName": "/tmp/test.cpp",
"FunctionName": "main",
"Line": 15,
"StartAddress": "0x4004be",
"StartFileName": "/tmp/test.cpp",
"StartLine": 14
}
]
},
{
"Address": "0x400486",
"ModuleName": "inlined.elf",
"Symbol": [
{
"Column": 3,
"Discriminator": 0,
"FileName": "/tmp/test.cpp",
"FunctionName": "foo()",
"Line": 6,
"StartAddress": "0x400486",
"StartFileName": "/tmp/test.cpp",
"StartLine": 5
}
]
}
]
--pretty-print,-pβ prints human readable output. if--inliningis on, the enclosing scope gets prefixed with(inlined by). for JSON output, this option makes the JSON indented and split across new lines β otherwise the JSON comes out all compact and squished. π
$ llvm-symbolizer --obj=inlined.elf 0x4004be --inlining --pretty-print
baz() at /tmp/test.cpp:11:18
(inlined by) main at /tmp/test.cpp:15:0
--print-address,--addresses,-aβ prints the address before the source code location. defaults to false.
$ llvm-symbolizer --obj=inlined.elf --print-address 0x4004be
0x4004be
baz()
/tmp/test.cpp:11:18
main
/tmp/test.cpp:15:0
$ llvm-symbolizer --obj=inlined.elf 0x4004be --pretty-print --print-address
0x4004be: baz() at /tmp/test.cpp:11:18
(inlined by) main at /tmp/test.cpp:15:0
--print-source-context-lines <N>β printsNlines of source context for each symbolized address. peak "let me see the receipts" behavior. π₯
$ llvm-symbolizer --obj=test.elf 0x400490 --print-source-context-lines=3
baz()
/tmp/test.cpp:11:0
10 : volatile int k = 42;
11 >: return foz() + k;
12 : }
--relativenamesβ prints the file's path relative to the compilation directory instead of the absolute path. but ngl, if the compiler's command-line already had the full path, this ends up being the same as the default. π--verboseβ prints verbose address, line and column information. all the tea. β
$ llvm-symbolizer --obj=inlined.elf --verbose 0x4004be
baz()
Filename: /tmp/test.cpp
Function start filename: /tmp/test.cpp
Function start line: 9
Function start address: 0x4004b6
Line: 11
Column: 18
main
Filename: /tmp/test.cpp
Function start filename: /tmp/test.cpp
Function start line: 14
Function start address: 0x4004b0
Line: 15
Column: 18
--version,-vβ prints version information for the tool. β¨@<FILE>β reads command-line options from a response file<FILE>. fancy.
πͺ WINDOWS/PDB SPECIFIC OPTIONS πͺ
--diaβ uses the Windows DIA SDK for symbolization. and if the DIA SDK isn't found?llvm-symbolizerfalls back to the native implementation. no drama. π
π MACH-O SPECIFIC OPTIONS π
--default-arch <arch>β if a binary contains object files for multiple architectures (say, it's a Mach-O universal binary), this symbolizes the object file for the architecture you name. you can also specify the architecture by writingbinary_name:arch_namein the input (peep the example below). and if the architecture isn't specified either way, the address just won't be symbolized. defaults to empty string. π€
$ cat addr.txt
/tmp/mach_universal_binary:i386 0x1f84
/tmp/mach_universal_binary:x86_64 0x100000f24
$ llvm-symbolizer < addr.txt
_main
/tmp/source_i386.cc:8
_main
/tmp/source_x86_64.cc:8
--dsym-hint <path/to/file.dSYM>β if the debug info for a binary isn't in the default location, go look for it at the.dSYMpath you hand over with this option. you can use this flag multiple times, stack 'em up. π«Ά
πͺ EXIT STATUS πͺ
llvm-symbolizer returns 0. any other exit code means there's an internal program error. so if you see anything that isn't 0, something went wrong inside and it's not your fault bestie. π
π SEE ALSO π
βοΈ AUTHOR βοΈ
Maintained by the LLVM Team (https://llvm.org/).
Β©οΈ COPYRIGHT Β©οΈ
2003-2024, LLVM Project
and that's the whole page, bestie, you made it to the end π this one's from the LLVM Project, version 15, dated 2024-04-14 β go forth and symbolize, you absolute icon ππ
π¦ where this page comes from
- ubuntu noble: llvm-16 1:16.0.6-23ubuntu4 Β· APACHE-2-LLVM-EXCEPTIONS
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms