/* Interfaces for libdwfl_stacktrace. XXX: This is an experimental initial version of the API, and is liable to change in future releases of elfutils, especially as we figure out how to generalize the work to other sample data formats in addition to perf_events. Copyright (C) 2025 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify it under the terms of either * the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version or * the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version or both in parallel, as here. elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received copies of the GNU General Public License and the GNU Lesser General Public License along with this program. If not, see . */ #ifndef _LIBDWFL_STACKTRACE_H #define _LIBDWFL_STACKTRACE_H 1 #include "libdwfl.h" #ifdef __cplusplus extern "C" { #endif /* Keeps track of and caches Elf structs across multiple libdwfl sessions corresponding to different processes. */ typedef struct Dwflst_Process_Tracker Dwflst_Process_Tracker; /* Initialize a new tracker for multiple libdwfl sessions. Since Elf data will shared between the libdwfl sessions, each Dwfl must use the same Dwfl_Callbacks CALLBACKS provided when the tracker is created. */ extern Dwflst_Process_Tracker *dwflst_tracker_begin (const Dwfl_Callbacks *callbacks) __nonnull_attribute__ (1); /* Create a new Dwfl linked to this tracker. */ extern Dwfl *dwflst_tracker_dwfl_begin (Dwflst_Process_Tracker *tracker) __nonnull_attribute__ (1); /* Try to find a cached Elf corresponding to MODULE_NAME. Verifies that the cached Elf has dev/ino/mtime matching the file on disk. Non-NULL MODULE_PATH specifies an alternate location for the module e.g. /proc/PID/root/MODULE_NAME. Stores FILE_NAME and ELFP values. Returns fd similar to the find_elf callbacks, or -1 if cached Elf was not found. */ extern int dwflst_tracker_find_cached_elf (Dwflst_Process_Tracker *tracker, const char *module_name, const char *module_path, char **file_name, Elf **elfp) __nonnull_attribute__ (1, 2, 4, 5); /* Store an Elf corresponding to MODULE_NAME in the tracker's cache. FILE_NAME and FD values must be provided, similar to the output of a find_elf callback. Returns TRUE iff the Elf was successfully stored in the cache. The tracker will retain the Elf* via libelf's reference counting mechanism, and release its reference during dwflst_tracker_end. */ extern bool dwflst_tracker_cache_elf (Dwflst_Process_Tracker *tracker, const char *module_name, const char *file_name, Elf *elf, int fd) __nonnull_attribute__ (1, 2); /* Find the Dwfl corresponding to PID. If CALLBACK is non-NULL and the Dwfl has not been created, invoke CALLBACK, which should return a Dwfl linked to the tracker (or NULL if Dwfl creation also fails). The Dwfl will be automatically added to the tracker's internal table when its pid is confirmed by calling dwfl_attach_state. Returns NULL if Dwfl was not found and callback failed. */ extern Dwfl *dwflst_tracker_find_pid (Dwflst_Process_Tracker *tracker, pid_t pid, Dwfl *(*callback) (Dwflst_Process_Tracker *tracker, pid_t pid, void *arg), void *arg) __nonnull_attribute__ (1); /* For implementing a find_elf callback based on the prior two functions. Returns the Dwflst_Process_Tracker corresponding to MOD. */ extern Dwflst_Process_Tracker *dwflst_module_gettracker (Dwfl_Module *mod); /* End all libdwfl sessions with this tracker. */ extern void dwflst_tracker_end (Dwflst_Process_Tracker *tracker); /* Adaptation of the dwfl_linux_proc_find_elf callback from libdwfl, except this first attempts to look up a cached Elf* and fd from the Dwfl_Module's Dwflst_Process_Tracker (if any). If a new Elf* is created, this callback saves it to the tracker's cache. The cache will retain the Elf* via libelf's reference counting mechanism, and release its reference during dwflst_tracker_end. */ extern int dwflst_tracker_linux_proc_find_elf (Dwfl_Module *mod, void **userdata, const char *module_name, Dwarf_Addr 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 (). */ 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, uint64_t perf_regs_mask, uint32_t abi, int (*callback) (Dwfl_Frame *state, void *arg), void *arg) __nonnull_attribute__ (1, 5, 7, 11); /* Returns the linux perf_events register mask describing a set of registers sufficient for unwinding on MACHINE, or 0 if libdwfl does not handle perf_events samples for MACHINE. Does not take a Dwfl* or Elf* since this is meant to allow a profiling tool to configure perf_events to produce meaningful data for a libdwfl session to be opened later. */ uint64_t dwflst_perf_sample_preferred_regs_mask (GElf_Half machine); #ifdef __cplusplus } #endif #endif /* libdwfl_stacktrace.h */