libsysprof-capture: use signed int for backtrace return

This allows us to more safely subtract 1 from the unw_backtrace() to get
the proper number of frames (and detect it in the collector).
This commit is contained in:
Christian Hergert
2020-02-18 14:03:19 -08:00
parent 9f43bf2813
commit 7490a774ab
3 changed files with 16 additions and 12 deletions

View File

@ -72,9 +72,9 @@ typedef struct _SysprofCaptureWriter SysprofCaptureWriter;
* *
* Returns: the number of addresses filled in @addrs * Returns: the number of addresses filled in @addrs
*/ */
typedef guint (*SysprofBacktraceFunc) (SysprofCaptureAddress *addrs, typedef gint (*SysprofBacktraceFunc) (SysprofCaptureAddress *addrs,
guint n_addrs, guint n_addrs,
gpointer user_data); gpointer user_data);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureWriter *sysprof_capture_writer_new_from_env (gsize buffer_size); SysprofCaptureWriter *sysprof_capture_writer_new_from_env (gsize buffer_size);

View File

@ -383,6 +383,8 @@ sysprof_collector_allocate (SysprofCaptureAddress alloc_addr,
if ((ev = mapped_ring_buffer_allocate (collector->buffer, len))) if ((ev = mapped_ring_buffer_allocate (collector->buffer, len)))
{ {
gint n_addrs;
/* First take a backtrace, so that backtrace_func() can overwrite /* First take a backtrace, so that backtrace_func() can overwrite
* a little bit of data *BEFORE* ev->addrs as stratch space. This * a little bit of data *BEFORE* ev->addrs as stratch space. This
* is useful to allow using unw_backtrace() or backtrace() to skip * is useful to allow using unw_backtrace() or backtrace() to skip
@ -392,9 +394,9 @@ sysprof_collector_allocate (SysprofCaptureAddress alloc_addr,
* scratch space anyway. * scratch space anyway.
*/ */
if (backtrace_func) if (backtrace_func)
ev->n_addrs = backtrace_func (ev->addrs, MAX_UNWIND_DEPTH, backtrace_data); n_addrs = backtrace_func (ev->addrs, MAX_UNWIND_DEPTH, backtrace_data);
else else
ev->n_addrs = 0; n_addrs = 0;
ev->frame.len = sizeof *ev + sizeof (SysprofCaptureAddress) * ev->n_addrs; ev->frame.len = sizeof *ev + sizeof (SysprofCaptureAddress) * ev->n_addrs;
ev->frame.type = SYSPROF_CAPTURE_FRAME_ALLOCATION; ev->frame.type = SYSPROF_CAPTURE_FRAME_ALLOCATION;
@ -404,6 +406,7 @@ sysprof_collector_allocate (SysprofCaptureAddress alloc_addr,
ev->tid = collector->tid; ev->tid = collector->tid;
ev->alloc_addr = alloc_addr; ev->alloc_addr = alloc_addr;
ev->alloc_size = alloc_size; ev->alloc_size = alloc_size;
ev->n_addrs = CLAMP (n_addrs, 0, MAX_UNWIND_DEPTH);
mapped_ring_buffer_advance (collector->buffer, ev->frame.len); mapped_ring_buffer_advance (collector->buffer, ev->frame.len);
} }

View File

@ -70,7 +70,7 @@ collector_init_ctor (void)
collector_ready = TRUE; collector_ready = TRUE;
} }
static guint static gint
backtrace_func (SysprofCaptureAddress *addrs, backtrace_func (SysprofCaptureAddress *addrs,
guint n_addrs, guint n_addrs,
gpointer user_data) gpointer user_data)
@ -82,7 +82,7 @@ backtrace_func (SysprofCaptureAddress *addrs,
* and subtract an offset from addrs to avoid having to * and subtract an offset from addrs to avoid having to
* copy frame pointers around. * copy frame pointers around.
*/ */
return unw_backtrace ((void **)addrs - 1, n_addrs); return unw_backtrace ((void **)addrs - 1, n_addrs) - 1;
# else # else
static const gint skip = 1; static const gint skip = 1;
void **stack = alloca (n_addrs * sizeof (gpointer)); void **stack = alloca (n_addrs * sizeof (gpointer));
@ -94,13 +94,14 @@ backtrace_func (SysprofCaptureAddress *addrs,
#elif defined(HAVE_EXECINFO_H) #elif defined(HAVE_EXECINFO_H)
# if GLIB_SIZEOF_VOID_P == 8 # if GLIB_SIZEOF_VOID_P == 8
/* See note on unw_backtrace() */ /* See note on unw_backtrace() */
return backtrace ((void **)addrs - 1, n_addrs); return backtrace ((void **)addrs - 1, n_addrs) - 1;
# else /* GLIB_SIZEOF_VOID_P != 8 */ # else /* GLIB_SIZEOF_VOID_P != 8 */
static const gint skip = 1;
void **stack = alloca (n_addrs * sizeof (gpointer)); void **stack = alloca (n_addrs * sizeof (gpointer));
guint n = backtrace (stack, n_addrs); gint n = backtrace (stack, n_addrs);
for (guint i = 0; i < n; i++) for (guint i = skip; i < n; i++)
addrs[i] = GPOINTER_TO_SIZE (stack[i]); addrs[i-skip] = GPOINTER_TO_SIZE (stack[i]);
return n; return MAX (0, n - skip);
# endif /* GLIB_SIZEOF_VOID_P */ # endif /* GLIB_SIZEOF_VOID_P */
#else #else
return 0; return 0;