From: Omar Sandoval <osan...@fb.com> The next change will need to have the Dwarf_Frame readily available, so rather than finding it again every time, let's cache it for reuse. The CFI frame can also be useful to clients of libdwfl, so add dwfl_frame_dwarf_frame to get it. Similarly, the Dwfl_Module is also frequently needed in conjunction with the frame, so cache it and add dwfl_frame_module.
Signed-off-by: Omar Sandoval <osan...@fb.com> --- libdw/ChangeLog | 2 ++ libdw/libdw.map | 2 ++ libdwfl/ChangeLog | 10 ++++++++++ libdwfl/dwfl_frame.c | 2 ++ libdwfl/frame_unwind.c | 25 +++++++++++++++++++++---- libdwfl/libdwfl.h | 10 ++++++++++ libdwfl/libdwflP.h | 5 +++++ 7 files changed, 52 insertions(+), 4 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 1de8e2fc..1a712497 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -3,6 +3,8 @@ * libdw.map (ELFUTILS_0.178): New section. Add dwfl_attach_thread. Add dwfl_detach_thread. + Add dwfl_frame_module. + Add dwfl_frame_dwarf_frame. 2019-07-05 Omar Sandoval <osan...@fb.com> diff --git a/libdw/libdw.map b/libdw/libdw.map index f20ffc2f..c1469c4e 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -374,4 +374,6 @@ ELFUTILS_0.178 { global: dwfl_attach_thread; dwfl_detach_thread; + dwfl_frame_module; + dwfl_frame_dwarf_frame; } ELFUTILS_0.177; diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index b7eaedca..fdb517c9 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -13,9 +13,19 @@ (attach_thread_cb): Add function. (dwfl_attach_thread): Add function. (dwfl_detach_thread): Add function. + (state_alloc): Initialize state->mod and state->frame. + * frame_unwind.c (new_unwound): Initialize state->mod and + state->frame. + (handle_cfi): Cache state->frame and state->bias. + (__libdwfl_frame_unwind): Cache state->mod. + (dwfl_frame_module): Add function. + (dwfl_frame_dwarf_frame): Add function. * libdwfl.h (dwfl_attach_thread): Add definition. (dwfl_detach_thread): Add definition. + (dwfl_frame_module): Add definition. + (dwfl_frame_dwarf_frame): Add definition. * libdwflP.h (struct Dwfl_Thread): Update comment for unwound member. + Add mod, frame, and bias. 2019-08-12 Mark Wielaard <m...@klomp.org> diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c index 61fad8b9..3f660f7e 100644 --- a/libdwfl/dwfl_frame.c +++ b/libdwfl/dwfl_frame.c @@ -94,6 +94,8 @@ state_alloc (Dwfl_Thread *thread) if (state == NULL) return NULL; state->thread = thread; + state->mod = NULL; + state->frame = NULL; state->signal_frame = false; state->initial_frame = true; state->pc_state = DWFL_FRAME_STATE_ERROR; diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c index d7dfa5a9..9738ca72 100644 --- a/libdwfl/frame_unwind.c +++ b/libdwfl/frame_unwind.c @@ -523,6 +523,8 @@ new_unwound (Dwfl_Frame *state) state->unwound = unwound; unwound->thread = thread; unwound->unwound = NULL; + unwound->mod = NULL; + unwound->frame = NULL; unwound->signal_frame = false; unwound->initial_frame = false; unwound->pc_state = DWFL_FRAME_STATE_ERROR; @@ -544,6 +546,8 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) __libdwfl_seterrno (DWFL_E_LIBDW); return; } + state->frame = frame; + state->bias = bias; Dwfl_Frame *unwound = new_unwound (state); if (unwound == NULL) @@ -724,20 +728,20 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) Then we need to unwind from the original, unadjusted PC. */ if (! state->initial_frame && ! state->signal_frame) pc--; - Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); - if (mod == NULL) + state->mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); + if (state->mod == NULL) __libdwfl_seterrno (DWFL_E_NO_DWARF); else { Dwarf_Addr bias; - Dwarf_CFI *cfi_eh = INTUSE(dwfl_module_eh_cfi) (mod, &bias); + Dwarf_CFI *cfi_eh = INTUSE(dwfl_module_eh_cfi) (state->mod, &bias); if (cfi_eh) { handle_cfi (state, pc - bias, cfi_eh, bias); if (state->unwound) return; } - Dwarf_CFI *cfi_dwarf = INTUSE(dwfl_module_dwarf_cfi) (mod, &bias); + Dwarf_CFI *cfi_dwarf = INTUSE(dwfl_module_dwarf_cfi) (state->mod, &bias); if (cfi_dwarf) { handle_cfi (state, pc - bias, cfi_dwarf, bias); @@ -770,3 +774,16 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); state->unwound->signal_frame = signal_frame; } + +Dwfl_Module * +dwfl_frame_module (Dwfl_Frame *state) +{ + return state->mod; +} + +Dwarf_Frame * +dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) +{ + *bias = state->bias; + return state->frame; +} diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h index a22afc78..b450816b 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -750,6 +750,16 @@ pid_t dwfl_thread_tid (Dwfl_Thread *thread) Dwfl_Thread *dwfl_frame_thread (Dwfl_Frame *state) __nonnull_attribute__ (1); +/* Return module containing the PC for frame STATE. Returns NULL if no module + contains the PC. */ +Dwfl_Module *dwfl_frame_module (Dwfl_Frame *state) + __nonnull_attribute__ (1); + +/* Return CFI frame for frame STATE. Returns NULL if no CFI frame was + found. */ +Dwarf_Frame *dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) + __nonnull_attribute__ (1, 2); + /* Called by Dwfl_Thread_Callbacks.set_initial_registers implementation. For every known continuous block of registers <FIRSTREG..FIRSTREG+NREGS) (inclusive..exclusive) set their content to REGS (array of NREGS items). diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index c80d2051..ea417596 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -255,6 +255,11 @@ struct Dwfl_Frame Dwfl_Thread *thread; /* Previous (outer) frame. */ Dwfl_Frame *unwound; + /* Module containing pc. */ + Dwfl_Module *mod; + /* CFI frame containing pc. */ + Dwarf_Frame *frame; + Dwarf_Addr bias; bool signal_frame : 1; bool initial_frame : 1; enum -- 2.23.0