Hello,
I've been concerned to get libdwfl_stacktrace out of the weird 'experimental'
limbo we put it in for the last elfutils release. To do that, we need to
stabilize the API.
My full prototype of a more mature API is delayed for reasons beyond my
control, but sometime in September is the likely ETA. For now I want to get
people's opinions (mjw? amerey?) on the most crucial change. To avoid depending
on the Linux kernel specific perf_events API, we need a
dwflst_sample_getframes() function that doesn't take perf_events formatted data.
The header-only patch below illustrates the planned API change.
The base solution is for dwflst_sample_getframes() to take a pointer to
regs_mapping, which, for each item in regs[] array, specifies its position in
the full register file expected by the DWARF functionality. (This avoids the
need to take a perf_events regs bitmap that can only be interpreted with the
aid of a weird enum header buried in the linux kernel tree.)
The regs_mapping array is most likely to stay constant for an entire profiling
session, so this is not a high-overhead interface.
(A bit controversially, I'm allowing n_regs_mapping != n_regs, which might
smoothly deal with cases where dwflst_sample_getframes is passed a profiling
data packet with malformed or truncated regs array.)
We *keep* the existing dwflst_perf_sample_getframes as a convenience variant of
dwflst_sample_getframes. It clearly says 'perf', and I think it's fine to have
this perf-specific API as long as it's not the *only* API.
I believe this is the most significant obstacle to turning libdwfl_stacktrace
into a stable API.
mjw, do any other major issues come to mind?
(I'm sure we will find minor things to fix when we bikeshed this header, of
course.)
I could add functions to generate a plausible regs_mapping for various
architectures,
though I'd like a non perf_events test case for that. I've looked at BSD
PmcTools,
for one example, but not 100% sure yet how to bolt libdwfl_stacktrace into it.
All the best,
Serhei
diff --git a/libdwfl_stacktrace/libdwfl_stacktrace.h b/libdwfl_stacktrace/libdw\
fl_stacktrace.h
index b236ddc4..b8987c6f 100644
--- a/libdwfl_stacktrace/libdwfl_stacktrace.h
+++ b/libdwfl_stacktrace/libdwfl_stacktrace.h
@@ -113,14 +113,28 @@ extern int dwflst_tracker_linux_proc_find_elf (Dwfl_Modul\
e *mod, void **userdata
const char *module_name, Dwarf_A\
ddr base,
char **file_name, Elf **);
-
/* Like dwfl_thread_getframes, but iterates through the frames for a
- linux perf_events stack sample rather than a live thread. Calls
- dwfl_attach_state on DWFL, with architecture specified by ELF, ELF
- must remain valid during Dwfl lifetime. Returns zero if all frames
- have been processed by the callback, returns -1 on error, or the
- value of the callback when not DWARF_CB_OK. -1 returned on error
- will set dwfl_errno (). */
+ stack sample rather than a live thread. Calls dwfl_attach_state on
+ DWFL, with architecture specified by ELF, ELF must remain vaild
+ during Dwfl lifetime. Returns zero if all frames have been
+ processed by the callback, returns -1 on error, or the value of the
+ callback when not DWARF_CB_OK. -1 returned on error will set
+ dwfl_errno (). */
+int dwflst_sample_getframes (Dwfl *dwfl, Elf *elf, pid_t pid, pid_t tid,
+ const void *stack, size_t stack_size,
+ const Dwarf_Word *regs, uint32_t n_regs,
+ const int *regs_mapping, uint32_t
n_regs_mapping,
+ int (*callback) (Dwfl_Frame *state, void
*arg),
+ void *arg)
+ __nonnull_attribute__ (1, 5, 7, 9, 11);
+
+/* Adapts dwflst_sample_getframes to linux perf_events stack sample
+ and register file data format. Calls dwfl_attach_state on DWFL,
+ with architecture specified by ELF, ELF must remain valid during
+ Dwfl lifetime. Returns zero if all frames have been processed by
+ the callback, returns -1 on error, or the value of the callback
+ when not DWARF_CB_OK. -1 returned on error will set dwfl_errno
+ (). */
int dwflst_perf_sample_getframes (Dwfl *dwfl, Elf *elf, pid_t pid, pid_t tid,
const void *stack, size_t stack_size,
const Dwarf_Word *regs, uint32_t n_regs,