This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch 4/4 v2] unwinder: The unwinder (x86* only)


On Mon, 17 Jun 2013 10:57:57 +0200, Mark Wielaard wrote:
> On Sat, 2013-06-15 at 18:27 +0200, Jan Kratochvil wrote:
> > typedef struct
> > {
> >   /* Called to iterate through threads.  Returns next TID (tthread ID) on
> >      success, a negative number on failure and zero if there are no more
> >      threads.  For successful results the implementation must call
> >      dwfl_thread_state on NTHREAD.  This method must not be NULL.  */
> >   pid_t (*next_thread) (Dwfl *dwfl, Dwfl_Thread *nthread, void *arg);
> 
> I think this should get Dwfl_Thread *pthread also as argument,
> indicating the previous thread (NULL on first call).

I do not see it useful.  In callbacks I wrote I need some internal iterator
stored in ARG.  What PTHREAD would be useful for?  At most for TID but naively
linearly looking up TID in the callback's data structures would typically lead
to n^2 time complexity, with some better data structures to n*log(n).
Still an iterator stored in ARG gives normal linear n time complexity.


Otherwise agreed, API updated.  I will refactor the code as we were talking
off-list.


Thanks,
Jan


typedef int bool;
typedef int pid_t;
typedef struct Dwfl Dwfl;
typedef struct Dwarf_Addr Dwarf_Addr;
typedef struct Dwarf_Word Dwarf_Word;
typedef struct Dwfl_Thread Dwfl_Thread;
typedef struct Dwfl_Frame Dwfl_Frame;

typedef struct
{
  /* Called to iterate through threads.  Returns next TID (tthread ID) on
     success, a negative number on failure and zero if there are no more
     threads.  For successful results the implementation must call
     dwfl_thread_state on NTHREAD.  This method must not be NULL.  */
  pid_t (*next_thread) (Dwfl *dwfl, Dwfl_Thread *nthread, void *arg);

  /* Called by dwfl_end.  All thread_detach method calls have been already
     done.  This method may be NULL.  */
  void (*detach) (Dwfl *dwfl, void *arg);

  /* Called during unwinding to access memory (stack) state.  Returns true for
     successfully read *RESULT or false and sets dwfl_err () on failure.  This
     method may be NULL - in such case dwfl_thread_getframes will return only
     the initial frame.  */
  bool (*memory_read) (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result,
                       void *arg);

  /* Called on initial unwind to get the initial register state of the first
     frame.  Should call dwfl_thread_state_registers, possibly multiple times
     for different ranges and possibly also dwfl_thread_state_register_pc, to
     fill in initial (DWARF) register values.  After this call, till at least
     thread_detach is called, the thread is assumed to be frozen, so that it is
     safe to unwind.  Returns true on success or false and sets dwfl_err () on
     failure.  This method must not be NULL.  */ 
  bool (*set_initial_registers) (Dwfl_Thread *thread, void *arg);

  /* Called when unwinding is done.  No callback will be called after
     this method has been called.  Iff set_initial_registers was called for
     a TID thread_detach will be called before the detach method above.
     This method may be NULL.  */
  void (*thread_detach) (Dwfl_Thread *thread, void *arg);
} Dwfl_Thread_Callbacks;

/* PID is the process id associated with the DWFL state, ARG is the
   callback backend state.  ARG will be provided to the callbacks.
   Function returns true on success, false otherwise.  */
bool dwfl_attach_state (Dwfl *dwfl, pid_t pid,
                        Dwfl_Thread_Callbacks *thread_callbacks, void *arg);

/* Return PID for the process associated with DWFL.  Function returns -1 if
   dwfl_attach_state was not called for DWFL.  */
pid_t dwfl_pid (Dwfl *dwfl);

/* Return DWFL from which THREAD was created using dwfl_next_thread.  */
Dwfl *dwfl_thread_dwfl (Dwfl_Thread *thread);

/* Return positive TID (thread ID) for THREAD.  This function never fails.  */
pid_t dwfl_thread_tid (Dwfl_Thread *thread);

/* 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).  */
void dwfl_thread_state_registers (Dwfl_Thread *thread, const int firstreg,
                                  unsigned nregs, const Dwarf_Word *regs);

/* Called by Dwfl_Thread_Callbacks.set_initial_registers implementation.
   If PC is not contained among DWARF registers passed by
   dwfl_thread_state_registers on the target architecture pass the PC value
   here.  */
void dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc);

/* Gets the next known thread, if any.  To get the initial thread
   provide NULL as previous thread PREV_THREAD.  */
Dwfl_Thread *dwfl_next_thread (Dwfl *dwfl, Dwfl_Thread *prev_thread);

/* Iterate through the frames for a thread.  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.  Keeps calling the
   callback with the next frame while the callback returns
   DWARF_CB_OK, till there are no more frames.  On start will call the
   set_initial_registers callback and on return will call the
   detach_thread callback of the Dwfl_Thread.  */
int dwfl_thread_getframes (Dwfl_Thread *thread,
                           int (*callback) (Dwfl_Frame *state, void *arg),
                           void *arg);

/* Return *PC (program counter) for thread-specific frame STATE.
   Set *ISACTIVATION according to DWARF frame "activation" definition.
   Typically you need to substract 1 from *PC if *ACTIVATION is false to safely
   find function of the caller.  ACTIVATION may be NULL.  PC must not be NULL.
   Function returns false if it failed to find *PC.  */
bool dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]