Uploading Debug Symbols
To generate meaningful profiling insights for native languages like Go, Rust, C, C++, or Haskell, Coralogix Continuous Profiling requires access to debug symbols (also called debuginfos). These symbols map raw memory addresses to human-readable function names, making stack traces, flame graphs, and performance data clear and actionable for developers.
Language support and symbol requirements
Coralogix Continuous Profiling uses debug symbols to provide human-readable insights such as function names and stack traces. These symbols are essential for profiling native languages but are not required for most managed runtimes.
Language | Symbol support needed? | Symbol type |
---|---|---|
Go | ✅ Yes | Embedded in ELF binary |
Rust | ✅ Yes | Embedded in ELF binary |
C / C++ | ✅ Yes | ELF .debug info |
Haskell | ✅ Yes | ELF .debug info |
Java | ❌ No (unless using JNI/native libs) | N/A |
Node.js | ❌ No | N/A |
Python | ❌ No | N/A |
.NET / C# | ❌ No | N/A |
For Java and other managed runtimes like Python or Node.js, profiling does not require symbol upload unless you are profiling native extensions (e.g., JNI libraries written in C/C++).
Symbol uploads are only required for native binaries—generally compiled to machine code and distributed as ELF executables or shared objects.
Ensure debug symbols are present
Many production build processes strip debug symbols from binaries by default to reduce size or obscure implementation details. However, symbols are essential for meaningful profiling.
To support this workflow:
- Build your binaries with debug symbols enabled.
- Upload the symbol-rich version to Coralogix using the
symbol-upload-tool
. - Optionally strip the symbols from the version you deploy to production.
This ensures profiling accuracy while keeping production binaries lean and secure.
Symbol-binary pairing: Match build IDs exactly
When uploading symbol files, it is critical that the uploaded file matches the exact build of the binary running in production. Specifically, the symbol file must share the same Build ID as the deployed binary.
Uploading symbols from a different build, even if the source code is identical, may result in incorrect or unusable profiling data.
Uploading symbols externally
Coralogix provides a CLI tool, symbol-upload-tool
, for uploading debug symbols out-of-band. This is typically integrated into your CI/CD pipeline, ensuring every production binary version is matched with its debug metadata.
Step 1: Install the CLI
Download the latest version of the CLI binary suitable for your system:
wget https://cgx.jfrog.io/artifactory/symbol-upload-tool/symbol-upload-tool-v0.0.5-`uname -m`-unknown-`uname -s | tr '[:upper:]' '[:lower:]'`-`( ldd --version 2>&1 | grep -qi musl && echo musl ) || echo gnu` -O symbol-upload-tool
Make the binary executable:
Step 2: Upload the debug symbols
Use the symbol-upload-tool
to upload your symbol-rich binary.
Replace <ENDPOINT>
, <AUTH>
, and <PATH>
with your actual values. The tool will extract and upload the debug symbols, associating them with the binary’s Build ID.
Placeholder | Description | Example Value |
---|---|---|
<ENDPOINT> | The Coralogix API endpoint where the symbols will be uploaded. This value changes based on your domain selection. | https://api.:443 |
<AUTH> | The API key used to authorize the upload. Any API key containing the Continuous Profiling permissions may be used. | xxxx_xxxxxxxxxxxxx |
<PATH> | The file path to the directory or binary containing debug symbols to upload. | ./checkoutservice |
Example:
./symbol-upload-tool upload --coralogix-endpoint <https://api.<span class="domain-value"></span>:443> --auth xxx_xxxxxxxxxxxxxxxxx ./checkoutservice
Overwriting existing symbols
If debug symbols for a given Build ID have already been uploaded—such as from a previous run or a different stage in your CI/CD pipeline—you can overwrite them using the --force
flag:
This guarantees Continuous Profiling uses the most complete and accurate symbol data available.
Uploading symbols for dynamic libraries (optional)
In addition to your main executable, your application likely depends on dynamic libraries (shared objects) that may also require debug symbols for comprehensive profiling. This step is optional and primarily useful when you want to resolve symbols for missing build IDs that correspond to dynamic libraries used by your application.
The process for uploading dynamic library symbols is identical to uploading executable symbols, but you first need to identify which libraries your application uses.
Step 1: Identify dynamic library dependencies
Use ldd
to list all dynamic libraries your application depends on:
Example output:
linux-vdso.so.1 (0x00007fff8e9fe000)
libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f8c2e8a0000)
libcrypto.so.1.1 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007f8c2e5d0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8c2e3e0000)
Step 1.5: Check if libraries are stripped
Before looking for debug symbols, verify whether the library files contain debug information:
# Check if a library has debug symbols
file /usr/lib/x86_64-linux-gnu/libssl.so.1.1
# Use readelf to check for debug sections
readelf -S /usr/lib/x86_64-linux-gnu/libssl.so.1.1 | grep debug
Example outputs:
# Library with debug symbols:
/usr/lib/x86_64-linux-gnu/libssl.so.1.1: ELF 64-bit LSO shared object, x86-64, version 1 (SYSV), dynamically linked, with debug_info, not stripped
# Stripped library:
/usr/lib/x86_64-linux-gnu/libssl.so.1.1: ELF 64-bit LSO shared object, x86-64, version 1 (SYSV), dynamically linked, stripped
readelf output examples:
# Library with debug symbols (shows debug sections):
[27] .debug_aranges PROGBITS 0000000000000000 001eb000
[28] .debug_info PROGBITS 0000000000000000 001eb040
[29] .debug_abbrev PROGBITS 0000000000000000 00292000
# Stripped library (no output, no debug sections found):
(no output)
If the output shows "stripped" or you don't see any debug sections, the library lacks debug symbols.
Step 1.6: Find separated debug symbols
If libraries are stripped, debug symbols are often stored separately in dedicated debug directories. Check these common locations:
# Standard debug directory
ls /usr/lib/debug/usr/lib/x86_64-linux-gnu/
ls /usr/lib/debug/lib/x86_64-linux-gnu/
# Build-ID based debug directory
ls /usr/lib/debug/.build-id/
# Distribution-specific locations
ls /lib/debug/
Debug symbol files are typically named with a .debug
extension or stored in directories that mirror the original library paths under /usr/lib/debug/
.
Step 2: Upload symbols for each library
For each library that contains debug symbols, upload them using the same symbol-upload-tool
. You can upload either the original library file (if it contains symbols) or the separated debug symbol file:
# Upload original library (if it contains debug symbols)
./symbol-upload-tool upload --coralogix-endpoint <ENDPOINT> --auth <AUTH> /usr/lib/x86_64-linux-gnu/libssl.so.1.1
# OR upload separated debug symbol file
./symbol-upload-tool upload --coralogix-endpoint <ENDPOINT> --auth <AUTH> /usr/lib/debug/usr/lib/x86_64-linux-gnu/libssl.so.1.1.debug
View all CLI options
To view the complete list of supported flags and options:
Example output:Usage: symbol-upload-tool upload [OPTIONS] --coralogix-endpoint <https://api.<span class="domain-value"></span>:443> --auth <AUTH> <PATH>
Arguments:
<PATH> Binaries paths to extract symbols from
Options:
--coralogix-endpoint <CORALOGIX_ENDPOINT>
--auth <AUTH>
--force Overwrite existing symbols
--description <DESCRIPTION> Optional description for the upload
--total-req-time <TOTAL_REQ_TIME> Timeout in seconds [default: 600]
-v, --verbose Enable verbose output
-h, --help Print help
Build ID types
Coralogix supports two methods for identifying binaries during symbol upload:
GNU build ID (default)
- A unique identifier embedded in ELF binaries, found in the
.note.gnu.build-id
section. To extract the GNU Build ID:
Or use
readelf
to inspect the binary directly:
File ID (fallback if no GNU build ID exists)
- If a binary does not include a GNU Build ID (e.g., stripped builds or custom toolchains), the
symbol-upload-tool
can generate a File ID based on the binary contents. - This ID is calculated deterministically using a hashing algorithm defined here.
To generate and view the File ID:
Coralogix will use the GNU Build ID when available. If not, it falls back to the File ID method to associate symbols with the binary. Ensure the same method is used during both upload and runtime.