std::string process::get_funcname(uintptr_t addr, bool demangle) const { try { const std::string& funcname = pelf_->get_funcname(addr); return demangle ? demangle_symbol(funcname) : funcname; } catch(...) {} return HT_UNKNOWN_FUNCTION; }
error stacktrace::trace( void ) { error result = SUCCESS(); void** buffer = new void*[max_stack_size]; stack_.clear(); int size = backtrace( buffer, max_stack_size ); if ( size ) { char** symbols = backtrace_symbols( buffer, size ); if ( symbols ) { for ( int i = 1; i < size; ++i ) { char* symbol = symbols[i]; if ( symbol ) { std::string demangled; std::string offset; demangle_symbol( symbol, demangled, offset ); stack_entry_t entry; entry.function = demangled; entry.offset = offset; entry.address = buffer[i]; stack_.push_back( entry ); } else { result = ERROR( NULL_VALUE_ERR, "Corrupt stack trace. Symbol is NULL." ); } } free( symbols ); } else { result = ERROR( NULL_VALUE_ERR, "Cannot generate stack symbols" ); } } else { result = ERROR( NULL_VALUE_ERR, "Stack trace is empty" ); } delete [] buffer; return result; }
int callstack_symbols( void** addresses, callstack_symbol_t* out_syms, int num_addresses, char* memory, int mem_size ) { int num_translated = 0; callstack_string_buffer_t outbuf = { memory, memory + mem_size }; memset( out_syms, 0x0, (size_t)num_addresses * sizeof(callstack_symbol_t) ); char** syms = backtrace_symbols( addresses, num_addresses ); size_t tmp_buf_len = 1024 * 32; char* tmp_buffer = (char*)malloc( tmp_buf_len ); FILE* addr2line = run_addr2line( addresses, num_addresses, tmp_buffer, tmp_buf_len ); for( int i = 0; i < num_addresses; ++i ) { char* symbol = syms[i]; unsigned int offset = 0; // find function name and offset #if defined(__linux) char* name_start = strchr( symbol, '(' ); char* offset_start = name_start ? strchr( name_start, '+' ) : 0x0; if( name_start && offset_start ) { // zero terminate all strings ++name_start; *offset_start = '\0'; ++offset_start; } #elif defined(__APPLE__) && defined(__MACH__) char* name_start = 0x0; char* offset_start = strrchr( symbol, '+' ); if( offset_start ) { offset_start[-1] = '\0'; ++offset_start; name_start = strrchr( symbol, ' ' ); if( name_start ) ++name_start; } #else # error "Unhandled platform" #endif if( name_start && offset_start ) { offset = (unsigned int)strtoll( offset_start, 0x0, 16 ); symbol = demangle_symbol( name_start, tmp_buffer, tmp_buf_len ); } out_syms[i].function = alloc_string( &outbuf, symbol, strlen( symbol ) ); out_syms[i].offset = offset; out_syms[i].file = "failed to lookup file"; out_syms[i].line = 0; if( addr2line != 0x0 ) { if( fgets( tmp_buffer, (int)tmp_buf_len, addr2line ) != 0x0 ) { #if defined(__linux) char* line_start = strchr( tmp_buffer, ':' ); *line_start = '\0'; if( tmp_buffer[0] != '?' && tmp_buffer[1] != '?' ) out_syms[i].file = alloc_string( &outbuf, tmp_buffer, strlen( tmp_buffer ) ); out_syms[i].line = (unsigned int)strtoll( line_start + 1, 0x0, 10 ); #elif defined(__APPLE__) && defined(__MACH__) char* file_start = strrchr( tmp_buffer, '('); if( file_start ) { ++file_start; char* line_start = strchr( file_start, ':' ); if( line_start ) { *line_start = '\0'; ++line_start; out_syms[i].file = alloc_string( &outbuf, file_start, strlen( file_start ) ); out_syms[i].line = (unsigned int)strtoll( line_start, 0x0, 10 ); } } #else # error "Unhandled platform" #endif } } ++num_translated; } free( syms ); free( tmp_buffer ); fclose( addr2line ); return num_translated; }
//for my personal convinience inline std::string demangle_symbol(const std::string& mangled_name) { return demangle_symbol(mangled_name.c_str()); }