static bool util_addr2line_lookup__(const void * bt_addr , char ** func_name , char ** file_name , int * line_nr, bool subtract_base_adress) { *func_name = NULL; // If dladdr() succeeds, but addr2line fails the func_name pointer will be set, but the function will return false anyway. *file_name = NULL; *line_nr = 0; { bool address_found = false; Dl_info dl_info; #if defined(__APPLE__) return false; #else if (dladdr(bt_addr , &dl_info)) { const char * executable = dl_info.dli_fname; *func_name = util_alloc_string_copy( dl_info.dli_sname ); if (util_file_exists( executable )) { char *stdout_file = util_alloc_tmp_file("/tmp" , "addr2line" , true); /* 1: Run addr2line application */ { char ** argv = util_calloc(3 , sizeof * argv ); argv[0] = util_alloc_string_copy("--functions"); argv[1] = util_alloc_sprintf("--exe=%s" , executable ); { char * rel_address = (char *) bt_addr; if (subtract_base_adress) rel_address -= (size_t) dl_info.dli_fbase; argv[2] = util_alloc_sprintf("%p" , (void *) rel_address); } util_fork_exec("addr2line" , 3 , (const char **) argv , true , NULL , NULL , NULL , stdout_file , NULL); util_free_stringlist(argv , 3); } /* 2: Parse stdout output */ { bool at_eof; FILE * stream = util_fopen(stdout_file , "r"); char * tmp_fname = util_fscanf_alloc_line(stream , &at_eof); if (strcmp(tmp_fname , UNDEFINED_FUNCTION) != 0) { char * stdout_file_name = util_fscanf_alloc_line(stream , &at_eof); char * line_string = NULL; util_binary_split_string( stdout_file_name , ":" , false , file_name , &line_string); if (line_string && util_sscanf_int( line_string , line_nr)) address_found = true; free( stdout_file_name ); util_safe_free( line_string ); } free( tmp_fname ); fclose(stream); } util_unlink_existing(stdout_file); free( stdout_file ); } } return address_found; #endif } }
static void util_addr2line_lookup(const char * executable , const char * bt_symbol , char ** func_name , char ** file_line) { char *tmp_file = util_alloc_tmp_file("/tmp" , "addr2line" , true); char * adress; { int start_pos = 0; int end_pos; while ( bt_symbol[start_pos] != '[') start_pos++; end_pos = start_pos; while ( bt_symbol[end_pos] != ']') end_pos++; adress = util_alloc_substring_copy( bt_symbol , start_pos + 1 , end_pos - start_pos - 1 ); } { char ** argv; argv = util_calloc(3 , sizeof * argv ); argv[0] = util_alloc_string_copy("--functions"); argv[1] = util_alloc_sprintf("--exe=%s" , executable); argv[2] = util_alloc_string_copy(adress); util_fork_exec("addr2line" , 3 , (const char **) argv , true , NULL , NULL , NULL , tmp_file , NULL); util_free_stringlist(argv , 3); } { bool at_eof; FILE * stream = util_fopen(tmp_file , "r"); *func_name = util_fscanf_alloc_line(stream , &at_eof); *file_line = util_fscanf_alloc_line(stream , &at_eof); fclose(stream); } util_unlink_existing(tmp_file); free(adress); free(tmp_file); }