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,