mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 16:08:04 +02:00
gallium/util: cache symbol lookup with libunwind
Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
parent
7c69ea553b
commit
91dfa02125
2 changed files with 94 additions and 27 deletions
|
|
@ -43,6 +43,62 @@
|
|||
#endif
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "os/os_thread.h"
|
||||
#include "u_hash_table.h"
|
||||
|
||||
struct util_hash_table* symbols_hash;
|
||||
static mtx_t symbols_mutex = _MTX_INITIALIZER_NP;
|
||||
|
||||
static unsigned hash_ptr(void* p)
|
||||
{
|
||||
return (unsigned)(uintptr_t)p;
|
||||
}
|
||||
|
||||
static int compare_ptr(void* a, void* b)
|
||||
{
|
||||
if(a == b)
|
||||
return 0;
|
||||
else if(a < b)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* TODO with some refactoring we might be able to re-use debug_symbol_name_cached()
|
||||
* instead.. otoh if using libunwind I think u_debug_symbol could just be excluded
|
||||
* from build?
|
||||
*/
|
||||
static const char *
|
||||
symbol_name_cached(unw_cursor_t *cursor, unw_proc_info_t *pip)
|
||||
{
|
||||
void *addr = (void *)(uintptr_t)pip->start_ip;
|
||||
char *name;
|
||||
|
||||
mtx_lock(&symbols_mutex);
|
||||
if(!symbols_hash)
|
||||
symbols_hash = util_hash_table_create(hash_ptr, compare_ptr);
|
||||
name = util_hash_table_get(symbols_hash, addr);
|
||||
if(!name)
|
||||
{
|
||||
char procname[256];
|
||||
unw_word_t off;
|
||||
int ret;
|
||||
|
||||
ret = unw_get_proc_name(cursor, procname, sizeof(procname), &off);
|
||||
if (ret && ret != -UNW_ENOMEM) {
|
||||
procname[0] = '?';
|
||||
procname[1] = 0;
|
||||
}
|
||||
|
||||
asprintf(&name, "%s%s", procname, ret == -UNW_ENOMEM ? "..." : "");
|
||||
|
||||
util_hash_table_set(symbols_hash, addr, (void*)name);
|
||||
}
|
||||
mtx_unlock(&symbols_mutex);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
void
|
||||
debug_backtrace_capture(struct debug_stack_frame *backtrace,
|
||||
unsigned start_frame,
|
||||
|
|
@ -52,7 +108,6 @@ debug_backtrace_capture(struct debug_stack_frame *backtrace,
|
|||
unw_context_t context;
|
||||
unw_proc_info_t pip;
|
||||
unsigned i = 0;
|
||||
int ret;
|
||||
|
||||
pip.unwind_info = NULL;
|
||||
|
||||
|
|
@ -63,39 +118,43 @@ debug_backtrace_capture(struct debug_stack_frame *backtrace,
|
|||
start_frame--;
|
||||
|
||||
while ((i < nr_frames) && (unw_step(&cursor) > 0)) {
|
||||
char procname[256];
|
||||
const char *filename;
|
||||
unw_word_t off;
|
||||
Dl_info dlinfo;
|
||||
unw_word_t ip;
|
||||
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||
unw_get_proc_info(&cursor, &pip);
|
||||
|
||||
ret = unw_get_proc_name(&cursor, procname, 256, &off);
|
||||
if (ret && ret != -UNW_ENOMEM) {
|
||||
procname[0] = '?';
|
||||
procname[1] = 0;
|
||||
}
|
||||
|
||||
if (dladdr((void *)(uintptr_t)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
|
||||
*dlinfo.dli_fname)
|
||||
filename = dlinfo.dli_fname;
|
||||
else
|
||||
filename = "?";
|
||||
|
||||
snprintf(backtrace[i].buf, sizeof(backtrace[i].buf),
|
||||
"%u: %s (%s%s+0x%x) [%p]", i, filename, procname,
|
||||
ret == -UNW_ENOMEM ? "..." : "", (int)off,
|
||||
(void *)(uintptr_t)(pip.start_ip + off));
|
||||
backtrace[i].start_ip = pip.start_ip;
|
||||
backtrace[i].off = ip - pip.start_ip;
|
||||
backtrace[i].procname = symbol_name_cached(&cursor, &pip);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
while (i < nr_frames) {
|
||||
backtrace[i].buf[0] = '\0';
|
||||
backtrace[i].start_ip = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static const void *
|
||||
frame_ip(const struct debug_stack_frame *frame)
|
||||
{
|
||||
return (void *)(uintptr_t)(frame->start_ip + frame->off);
|
||||
}
|
||||
|
||||
static const char *
|
||||
frame_filename(const struct debug_stack_frame *frame)
|
||||
{
|
||||
Dl_info dlinfo;
|
||||
|
||||
|
||||
if (dladdr(frame_ip(frame), &dlinfo) && dlinfo.dli_fname &&
|
||||
*dlinfo.dli_fname)
|
||||
return dlinfo.dli_fname;
|
||||
|
||||
return "?";
|
||||
}
|
||||
|
||||
void
|
||||
debug_backtrace_dump(const struct debug_stack_frame *backtrace,
|
||||
unsigned nr_frames)
|
||||
|
|
@ -103,9 +162,12 @@ debug_backtrace_dump(const struct debug_stack_frame *backtrace,
|
|||
unsigned i;
|
||||
|
||||
for (i = 0; i < nr_frames; ++i) {
|
||||
if (backtrace[i].buf[0] == '\0')
|
||||
if (!backtrace[i].start_ip)
|
||||
break;
|
||||
debug_printf("\t%s\n", backtrace[i].buf);
|
||||
debug_printf("\t%u: %s (%s+0x%x) [%p]\n", i,
|
||||
frame_filename(&backtrace[i]),
|
||||
backtrace[i].procname, backtrace[i].off,
|
||||
frame_ip(&backtrace[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,9 +179,12 @@ debug_backtrace_print(FILE *f,
|
|||
unsigned i;
|
||||
|
||||
for (i = 0; i < nr_frames; ++i) {
|
||||
if (backtrace[i].buf[0] == '\0')
|
||||
if (!backtrace[i].start_ip)
|
||||
break;
|
||||
fprintf(f, "\t%s\n", backtrace[i].buf);
|
||||
fprintf(f, "\t%u: %s (%s+0x%x) [%p]\n", i,
|
||||
frame_filename(&backtrace[i]),
|
||||
backtrace[i].procname, backtrace[i].off,
|
||||
frame_ip(&backtrace[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,9 @@ extern "C" {
|
|||
struct debug_stack_frame
|
||||
{
|
||||
#ifdef HAVE_LIBUNWIND
|
||||
char buf[128];
|
||||
unw_word_t start_ip;
|
||||
unsigned int off;
|
||||
const char *procname;
|
||||
#else
|
||||
const void *function;
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue