Mesa (master): gallium/android: Rewrite backtrace helper for android
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Wed Aug 5 18:25:46 UTC 2020
Module: Mesa
Branch: master
Commit: 5ae7098ebab1d15fa903d8888a1a73058e5976ff
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=5ae7098ebab1d15fa903d8888a1a73058e5976ff
Author: Kristian H. Kristensen <hoegsberg at google.com>
Date: Tue Jul 28 21:24:45 2020 -0700
gallium/android: Rewrite backtrace helper for android
The previous implementation kept a hashtable of a Backtrace object per
thread. debug_backtrace_capture is supposed to store a backtrace in
the passed in debug_stack_frame array, but instead overwrote the
per-thread Backtrace object.
This new version works more like the libunwind based capture. We hash
the file and symbol names and store pointers in the debug_stack_frame
struct. This way debug_backtrace_capture doesn't overwrite previous
captures or allocate memory that needs to be freed.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6112>
---
src/util/u_debug_stack.h | 8 ++-
src/util/u_debug_stack_android.cpp | 116 ++++++++++++++++++++-----------------
2 files changed, 68 insertions(+), 56 deletions(-)
diff --git a/src/util/u_debug_stack.h b/src/util/u_debug_stack.h
index fff41a5a9ea..8a36a66a08e 100644
--- a/src/util/u_debug_stack.h
+++ b/src/util/u_debug_stack.h
@@ -59,10 +59,12 @@ extern "C" {
*/
struct debug_stack_frame
{
-#ifdef HAVE_LIBUNWIND
- unw_word_t start_ip;
- unsigned int off;
+#if defined(HAVE_ANDROID_PLATFORM) || defined(HAVE_LIBUNWIND)
const char *procname;
+ uint64_t start_ip;
+ unsigned off;
+ const char *map;
+ unsigned int map_off;
#else
const void *function;
#endif
diff --git a/src/util/u_debug_stack_android.cpp b/src/util/u_debug_stack_android.cpp
index 879b0fb2e9d..061707c6790 100644
--- a/src/util/u_debug_stack_android.cpp
+++ b/src/util/u_debug_stack_android.cpp
@@ -28,84 +28,94 @@
#include "util/hash_table.h"
#include "os/os_thread.h"
-static hash_table *backtrace_table;
+static hash_table *symbol_table;
static mtx_t table_mutex = _MTX_INITIALIZER_NP;
+static const char *
+intern_symbol(const char *symbol)
+{
+ if (!symbol_table)
+ symbol_table = _mesa_hash_table_create(NULL, NULL, _mesa_key_string_equal);
+
+ uint32_t hash = _mesa_hash_string(symbol);
+ hash_entry *entry =
+ _mesa_hash_table_search_pre_hashed(symbol_table, hash, symbol);
+ if (!entry)
+ entry = _mesa_hash_table_insert_pre_hashed(symbol_table, hash, symbol, strdup(symbol));
+
+ return (const char *) entry->data;
+}
+
void
-debug_backtrace_capture(debug_stack_frame *mesa_backtrace,
+debug_backtrace_capture(debug_stack_frame *backtrace,
unsigned start_frame,
unsigned nr_frames)
{
- hash_entry *backtrace_entry;
- Backtrace *backtrace;
- pid_t tid = gettid();
+ Backtrace *bt;
if (!nr_frames)
return;
- /* We keep an Android Backtrace handler around for each thread */
+ bt = Backtrace::Create(BACKTRACE_CURRENT_PROCESS,
+ BACKTRACE_CURRENT_THREAD);
+ if (bt == NULL) {
+ for (unsigned i = 0; i < nr_frames; i++)
+ backtrace[i].procname = NULL;
+ return;
+ }
+
+ /* Add one to exclude this call. Unwind already ignores itself. */
+ bt->Unwind(start_frame + 1);
+
mtx_lock(&table_mutex);
- if (!backtrace_table)
- backtrace_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- backtrace_entry = _mesa_hash_table_search(backtrace_table, (void*) (uintptr_t)tid);
- if (!backtrace_entry) {
- backtrace = Backtrace::Create(getpid(), tid);
- _mesa_hash_table_insert(backtrace_table, (void*) (uintptr_t)tid, backtrace);
- } else {
- backtrace = (Backtrace *) backtrace_entry->data;
+
+ for (unsigned i = 0; i < nr_frames; i++) {
+ const backtrace_frame_data_t* frame = bt->GetFrame(i);
+ if (frame) {
+ backtrace[i].procname = intern_symbol(frame->func_name.c_str());
+ backtrace[i].start_ip = frame->pc;
+ backtrace[i].off = frame->func_offset;
+ backtrace[i].map = intern_symbol(frame->map.Name().c_str());
+ backtrace[i].map_off = frame->rel_pc;
+ } else {
+ backtrace[i].procname = NULL;
+ }
}
+
mtx_unlock(&table_mutex);
- /* Add one to exclude this call. Unwind already ignores itself. */
- backtrace->Unwind(start_frame + 1);
-
- /* Store the Backtrace handler in the first mesa frame for reference.
- * Unwind will generally return less frames than nr_frames specified
- * but we have no good way of storing the real count otherwise.
- * The Backtrace handler only stores the results until the next Unwind,
- * but that is how u_debug_stack is used anyway.
- */
- mesa_backtrace->function = backtrace;
+ delete bt;
}
void
-debug_backtrace_dump(const debug_stack_frame *mesa_backtrace,
+debug_backtrace_dump(const debug_stack_frame *backtrace,
unsigned nr_frames)
{
- Backtrace *backtrace = (Backtrace *) mesa_backtrace->function;
- size_t i;
-
- if (!nr_frames)
- return;
-
- if (nr_frames > backtrace->NumFrames())
- nr_frames = backtrace->NumFrames();
- for (i = 0; i < nr_frames; i++) {
- /* There is no prescribed format and this isn't interpreted further,
- * so we simply use the default Android format.
- */
- const std::string& frame_line = backtrace->FormatFrameData(i);
- debug_printf("%s\n", frame_line.c_str());
+ for (unsigned i = 0; i < nr_frames; i++) {
+ if (backtrace[i].procname)
+ debug_printf(
+ "%s(+0x%x)\t%012" PRIx64 ": %s+0x%x\n",
+ backtrace[i].map,
+ backtrace[i].map_off,
+ backtrace[i].start_ip,
+ backtrace[i].procname,
+ backtrace[i].off);
}
}
void
debug_backtrace_print(FILE *f,
- const debug_stack_frame *mesa_backtrace,
+ const debug_stack_frame *backtrace,
unsigned nr_frames)
{
- Backtrace *backtrace = (Backtrace *) mesa_backtrace->function;
- size_t i;
-
- if (!nr_frames)
- return;
-
- if (nr_frames > backtrace->NumFrames())
- nr_frames = backtrace->NumFrames();
- for (i = 0; i < nr_frames; i++) {
- const std::string& frame_line = backtrace->FormatFrameData(i);
- fprintf(f, "%s\n", frame_line.c_str());
+ for (unsigned i = 0; i < nr_frames; i++) {
+ if (backtrace[i].procname)
+ fprintf(f,
+ "%s(+0x%x)\t%012" PRIx64 ": %s+0x%x\n",
+ backtrace[i].map,
+ backtrace[i].map_off,
+ backtrace[i].start_ip,
+ backtrace[i].procname,
+ backtrace[i].off);
}
}
More information about the mesa-commit
mailing list