[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