diff options
Diffstat (limited to 'libdwfl/dwfl_frame.c')
-rw-r--r-- | libdwfl/dwfl_frame.c | 66 |
1 files changed, 22 insertions, 44 deletions
diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c index 881f735a..5bbf850e 100644 --- a/libdwfl/dwfl_frame.c +++ b/libdwfl/dwfl_frame.c @@ -71,19 +71,14 @@ state_fetch_pc (Dwfl_Frame *state) /* Do not call it on your own, to be used by thread_* functions only. */ static void -state_free (Dwfl_Frame *state) +free_states (Dwfl_Frame *state) { - Dwfl_Thread *thread = state->thread; - assert (thread->unwound == state); - thread->unwound = state->unwound; - free (state); -} - -static void -thread_free_all_states (Dwfl_Thread *thread) -{ - while (thread->unwound) - state_free (thread->unwound); + while (state) + { + Dwfl_Frame *next = state->unwound; + free(state); + state = next; + } } static Dwfl_Frame * @@ -279,24 +274,15 @@ dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread *thread, void *arg), process->callbacks_arg, &thread.callbacks_arg); if (thread.tid < 0) - { - Dwfl_Error saved_errno = dwfl_errno (); - thread_free_all_states (&thread); - __libdwfl_seterrno (saved_errno); - return -1; - } + return -1; if (thread.tid == 0) { - thread_free_all_states (&thread); __libdwfl_seterrno (DWFL_E_NOERROR); return 0; } int err = callback (&thread, arg); if (err != DWARF_CB_OK) - { - thread_free_all_states (&thread); - return err; - } + return err; assert (thread.unwound == NULL); } /* NOTREACHED */ @@ -356,11 +342,8 @@ getthread (Dwfl *dwfl, pid_t tid, if (process->callbacks->get_thread (dwfl, tid, process->callbacks_arg, &thread.callbacks_arg)) { - int err; thread.tid = tid; - err = callback (&thread, arg); - thread_free_all_states (&thread); - return err; + return callback (&thread, arg); } return -1; @@ -411,12 +394,6 @@ dwfl_thread_getframes (Dwfl_Thread *thread, int (*callback) (Dwfl_Frame *state, void *arg), void *arg) { - if (thread->unwound != NULL) - { - /* We had to be called from inside CALLBACK. */ - __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT); - return -1; - } Ebl *ebl = thread->process->ebl; if (ebl_frame_nregs (ebl) == 0) { @@ -432,33 +409,34 @@ dwfl_thread_getframes (Dwfl_Thread *thread, if (! process->callbacks->set_initial_registers (thread, thread->callbacks_arg)) { - thread_free_all_states (thread); + free_states (thread->unwound); + thread->unwound = NULL; return -1; } - if (! state_fetch_pc (thread->unwound)) + Dwfl_Frame *state = thread->unwound; + thread->unwound = NULL; + if (! state_fetch_pc (state)) { if (process->callbacks->thread_detach) process->callbacks->thread_detach (thread, thread->callbacks_arg); - thread_free_all_states (thread); + free_states (state); return -1; } - - Dwfl_Frame *state; do { - state = thread->unwound; int err = callback (state, arg); if (err != DWARF_CB_OK) { if (process->callbacks->thread_detach) process->callbacks->thread_detach (thread, thread->callbacks_arg); - thread_free_all_states (thread); + free_states (state); return err; } __libdwfl_frame_unwind (state); + Dwfl_Frame *next = state->unwound; /* The old frame is no longer needed. */ - state_free (thread->unwound); - state = thread->unwound; + free (state); + state = next; } while (state && state->pc_state == DWFL_FRAME_STATE_PC_SET); @@ -467,12 +445,12 @@ dwfl_thread_getframes (Dwfl_Thread *thread, process->callbacks->thread_detach (thread, thread->callbacks_arg); if (state == NULL || state->pc_state == DWFL_FRAME_STATE_ERROR) { - thread_free_all_states (thread); + free_states (state); __libdwfl_seterrno (err); return -1; } assert (state->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED); - thread_free_all_states (thread); + free_states (state); return 0; } INTDEF(dwfl_thread_getframes) |