[PATCH 4/5] libdwfl: cache Dwfl_Module and Dwarf_Frame for Dwfl_Frame
Omar Sandoval
osandov@osandov.com
Mon Oct 7 09:05:00 GMT 2019
From: Omar Sandoval <osandov@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 <osandov@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 <osandov@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 <mark@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
More information about the Elfutils-devel
mailing list