#include "defs.h"
#include "unwind.h"
-#include "mmap_cache.h"
+#include "mmap_notify.h"
#include <elfutils/libdwfl.h>
struct ctx {
Dwfl *dwfl;
+ unsigned int last_proc_updating;
};
+static unsigned int mapping_generation;
+
+static void
+update_mapping_generation(struct tcb *tcp, void *unused)
+{
+ mapping_generation++;
+}
+
+static void
+init(void)
+{
+ mmap_notify_register_client(update_mapping_generation, NULL);
+}
+
static void *
tcb_init(struct tcb *tcp)
{
struct ctx *ctx = xmalloc(sizeof(*ctx));
ctx->dwfl = dwfl;
+ ctx->last_proc_updating = 0;
return ctx;
}
}
}
+static void
+flush_cache_maybe(struct tcb *tcp)
+{
+ struct ctx *ctx = tcp->unwind_ctx;
+ if (!ctx)
+ return;
+
+ if (ctx->last_proc_updating == mapping_generation)
+ return;
+
+ int r = dwfl_linux_proc_report(ctx->dwfl, tcp->pid);
+
+ if (r < 0)
+ error_msg("dwfl_linux_proc_report returned an error"
+ " for pid %d: %s", tcp->pid, dwfl_errmsg(-1));
+ else if (r > 0)
+ error_msg("dwfl_linux_proc_report returned an error"
+ " for pid %d", tcp->pid);
+ else if (dwfl_report_end(ctx->dwfl, NULL, NULL) != 0)
+ error_msg("dwfl_report_end returned an error"
+ " for pid %d: %s", tcp->pid, dwfl_errmsg(-1));
+
+ ctx->last_proc_updating = mapping_generation;
+}
+
struct frame_user_data {
unwind_call_action_fn call_action;
unwind_error_action_fn error_action;
.data = data,
.stack_depth = 256,
};
+
+ flush_cache_maybe(tcp);
+
int r = dwfl_getthread_frames(ctx->dwfl, tcp->pid, frame_callback,
&user_data);
if (r)
0);
}
-static void
-tcb_flush_cache(struct tcb *tcp)
-{
- struct ctx *ctx = tcp->unwind_ctx;
- if (!ctx)
- return;
-
- int r = dwfl_linux_proc_report(ctx->dwfl, tcp->pid);
-
- if (r < 0)
- error_msg("dwfl_linux_proc_report returned an error"
- " for pid %d: %s", tcp->pid, dwfl_errmsg(-1));
- else if (r > 0)
- error_msg("dwfl_linux_proc_report returned an error"
- " for pid %d", tcp->pid);
- else if (dwfl_report_end(ctx->dwfl, NULL, NULL) != 0)
- error_msg("dwfl_report_end returned an error"
- " for pid %d: %s", tcp->pid, dwfl_errmsg(-1));
-}
-
const struct unwind_unwinder_t unwinder = {
.name = "libdw",
- .init = NULL,
+ .init = init,
.tcb_init = tcb_init,
.tcb_fin = tcb_fin,
.tcb_walk = tcb_walk,
- .tcb_flush_cache = tcb_flush_cache,
};
static void
init(void)
{
+ mmap_cache_enable();
+
libunwind_as = unw_create_addr_space(&_UPT_accessors, 0);
if (!libunwind_as)
error_msg_and_die("failed to create address space"
}
static void
-tcb_walk(struct tcb *tcp,
- unwind_call_action_fn call_action,
- unwind_error_action_fn error_action,
- void *data)
+walk(struct tcb *tcp,
+ unwind_call_action_fn call_action,
+ unwind_error_action_fn error_action,
+ void *data)
{
char *symbol_name;
size_t symbol_name_size = 40;
}
static void
-tcb_flush_cache(struct tcb *tcp)
+tcb_walk(struct tcb *tcp,
+ unwind_call_action_fn call_action,
+ unwind_error_action_fn error_action,
+ void *data)
{
- unw_flush_cache(libunwind_as, 0, 0);
+ switch (mmap_cache_rebuild_if_invalid(tcp, __func__)) {
+ case MMAP_CACHE_REBUILD_RENEWED:
+ /*
+ * Rebuild the unwinder internal cache.
+ * Called when mmap cache subsystem detects a
+ * change of tracee memory mapping.
+ */
+ unw_flush_cache(libunwind_as, 0, 0);
+ ATTRIBUTE_FALLTHROUGH;
+ case MMAP_CACHE_REBUILD_READY:
+ walk(tcp, call_action, error_action, data);
+ break;
+ default:
+ /* Do nothing */
+ ;
+ }
}
const struct unwind_unwinder_t unwinder = {
.tcb_init = tcb_init,
.tcb_fin = tcb_fin,
.tcb_walk = tcb_walk,
- .tcb_flush_cache = tcb_flush_cache,
};
*/
#include "defs.h"
-#include "mmap_cache.h"
#include "unwind.h"
#ifdef USE_DEMANGLE
{
if (unwinder.init)
unwinder.init();
- mmap_cache_enable();
}
void
debug_func_msg("head: tcp=%p, queue=%p",
tcp, tcp->unwind_queue->head);
queue_print(tcp->unwind_queue);
- } else switch (mmap_cache_rebuild_if_invalid(tcp, __func__)) {
- case MMAP_CACHE_REBUILD_RENEWED:
- unwinder.tcb_flush_cache(tcp);
- ATTRIBUTE_FALLTHROUGH;
- case MMAP_CACHE_REBUILD_READY:
- debug_func_msg("walk: tcp=%p, queue=%p",
- tcp, tcp->unwind_queue->head);
- unwinder.tcb_walk(tcp, print_call_cb, print_error_cb, NULL);
- break;
- default:
- /* Do nothing */
- ;
- }
+ } else
+ unwinder.tcb_walk(tcp, print_call_cb, print_error_cb, NULL);
}
/*
#endif
if (tcp->unwind_queue->head)
error_msg_and_die("bug: unprinted entries in queue");
-
- switch (mmap_cache_rebuild_if_invalid(tcp, __func__)) {
- case MMAP_CACHE_REBUILD_RENEWED:
- unwinder.tcb_flush_cache(tcp);
- ATTRIBUTE_FALLTHROUGH;
- case MMAP_CACHE_REBUILD_READY:
- unwinder.tcb_walk(tcp, queue_put_call, queue_put_error,
- tcp->unwind_queue);
- debug_func_msg("tcp=%p, queue=%p",
+ else {
+ debug_func_msg("walk: tcp=%p, queue=%p",
tcp, tcp->unwind_queue->head);
- break;
- default:
- /* Do nothing */
- ;
+ unwinder.tcb_walk(tcp, queue_put_call, queue_put_error,
+ tcp->unwind_queue);
}
}
unwind_call_action_fn,
unwind_error_action_fn,
void *);
-
- /*
- * Rebuild the unwinder internal cache. Called when mmap cache
- * subsystem detects a change of tracee memory mapping.
- */
- void (*tcb_flush_cache)(struct tcb *);
};
extern const struct unwind_unwinder_t unwinder;