### Resolve PC Address to Source Info with backtrace_pcinfo (C) Source: https://context7.com/ianlancetaylor/libbacktrace/llms.txt The backtrace_pcinfo function resolves a single program counter (PC) address to its corresponding file, line number, and function name. It can handle inlined functions by invoking a callback multiple times. This example demonstrates how to use it to resolve addresses and print detailed information, including handling cases where debug information is unavailable or errors occur. The callback returns 0 to continue processing all inline levels. ```c #include #include #include #include "backtrace.h" struct pcinfo_data { const char *filename; int lineno; const char *function; int call_count; int failed; }; /* Callback for pcinfo - may be called multiple times for inlined functions */ static int pcinfo_callback(void *data, uintptr_t pc, const char *filename, int lineno, const char *function) { struct pcinfo_data *pdata = (struct pcinfo_data *)data; pdata->call_count++; if (pdata->call_count == 1) { /* Store first (innermost) result */ pdata->filename = filename; pdata->lineno = lineno; pdata->function = function; } printf(" [Inline level %d] %s at %s:%d\n", pdata->call_count, function ? function : "???", filename ? filename : "???", lineno); return 0; /* Continue to get all inline levels */ } static void pcinfo_error_callback(void *data, const char *msg, int errnum) { struct pcinfo_data *pdata = (struct pcinfo_data *)data; if (errnum == -1) { /* Special case: no debug info available */ fprintf(stderr, "No debug info: %s\n", msg); } else { fprintf(stderr, "Error: %s", msg); if (errnum > 0) fprintf(stderr, ": %s", strerror(errnum)); fprintf(stderr, "\n"); } pdata->failed = 1; } void resolve_addresses(struct backtrace_state *state, uintptr_t *addrs, size_t count) { for (size_t i = 0; i < count; i++) { struct pcinfo_data data = { 0 }; int ret; printf("Address 0x%lx:\n", (unsigned long)addrs[i]); ret = backtrace_pcinfo( state, addrs[i], pcinfo_callback, pcinfo_error_callback, &data ); if (ret == 0 && !data.failed && data.call_count > 0) { printf(" -> Resolved to: %s() in %s:%d\n\n", data.function ? data.function : "unknown", data.filename ? data.filename : "unknown", data.lineno); } } } /* Expected output for inlined functions: Address 0x401234: [Inline level 1] inner_function at /path/file.c:10 [Inline level 2] middle_function at /path/file.c:25 [Inline level 3] outer_function at /path/file.c:40 -> Resolved to: inner_function() in /path/file.c:10 */ ``` -------------------------------- ### Print Human-Readable Backtrace with backtrace_print (C) Source: https://context7.com/ianlancetaylor/libbacktrace/llms.txt The backtrace_print function outputs a human-readable backtrace to a specified FILE stream. It's useful for debugging and error reporting. This example shows how to use it within a signal handler for crash reporting and also for logging errors during runtime. It requires debug information and uses backtrace_full internally. Errors during backtrace generation are reported to stderr. ```c #include #include #include #include "backtrace.h" static struct backtrace_state *global_state; static void error_callback(void *data, const char *msg, int errnum) { fprintf(stderr, "backtrace error: %s", msg); if (errnum > 0) fprintf(stderr, ": %s", strerror(errnum)); fprintf(stderr, "\n"); } /* Signal handler that prints backtrace on crash */ void crash_handler(int sig) { fprintf(stderr, "\n=== CRASH: Signal %d ===\n", sig); /* Print backtrace to stderr, skip 2 frames (handler + signal trampoline) */ backtrace_print(global_state, 2, stderr); exit(1); } void problematic_function(void) { /* Simulate error condition - print backtrace for debugging */ fprintf(stderr, "Error occurred, printing backtrace:\n"); backtrace_print(global_state, 0, stderr); /* Or print to a log file */ FILE *logfile = fopen("error.log", "a"); if (logfile) { fprintf(logfile, "=== Error backtrace ===\n"); backtrace_print(global_state, 0, logfile); fclose(logfile); } } int main(int argc, char **argv) { global_state = backtrace_create_state(NULL, 1, error_callback, NULL); /* Install crash handler */ signal(SIGSEGV, crash_handler); signal(SIGABRT, crash_handler); problematic_function(); return 0; } /* Expected stderr output: Error occurred, printing backtrace: 0x401234 problematic_function /path/to/example.c:35 0x401300 main /path/to/example.c:52 0x7f123456 __libc_start_main ???:0 */ ``` -------------------------------- ### Implement Conditional Backtrace Support in C Source: https://context7.com/ianlancetaylor/libbacktrace/llms.txt Demonstrates how to use macros from backtrace-supported.h to initialize the backtrace state and perform safe operations based on platform capabilities. It handles scenarios where backtracing is unsupported, requires malloc, or lacks data symbol support. ```c #include "backtrace.h" #include "backtrace-supported.h" #if BACKTRACE_SUPPORTED static struct backtrace_state *state; void init_backtrace(const char *filename) { state = backtrace_create_state( filename, BACKTRACE_SUPPORTS_THREADS, error_callback, NULL ); } void print_trace(void) { #if !BACKTRACE_USES_MALLOC backtrace_print(state, 0, stderr); #else fprintf(stderr, "Backtrace (may not be signal-safe):\n"); backtrace_print(state, 0, stderr); #endif } void lookup_variable_symbol(uintptr_t addr) { #if BACKTRACE_SUPPORTS_DATA backtrace_syminfo(state, addr, syminfo_callback, error_callback, NULL); #else fprintf(stderr, "Variable symbol lookup not supported on this platform\n"); #endif } #else void init_backtrace(const char *filename) { (void)filename; fprintf(stderr, "Warning: backtrace not supported on this platform\n"); } void print_trace(void) { fprintf(stderr, "Backtrace not available\n"); } #endif ```