This is the mail archive of the 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 Thu, 13 Jun 2013 15:38:33 +0200, Mark Wielaard wrote:
> typedef struct Dwfl_Thread;
  typedef struct Dwfl_Thread Dwfl_Thread;
> typedef struct
> {
>   /* Called to iterate through threads.  Starting with previous *ptid
>      set to -1.  Returns next thread id on success, a negative number on
>      failure and zero if there are no more threads.  Should call
>      dwfl_thread_state () on nthread if thread can be unwound with
>      initial register and memory accessors.  */
>   pid_t (*next_thread) (Dwfl *dwfl, pid_t pid, pid_t *ptid,
>                         Dwfl_Thread *nthread, void *arg);

>   /* Called by dwfl_end ().  */
>   void (*detach) (Dwfl *dwfl, pid_t pid, void *arg);
> } Dwfl_State_Callbacks;

Couldn't it be merged together with Dwfl_Thread_Callbacks?
This would also remove the dwfl_thread_state function.
Dwfl_Thread_Callbacks->memory_read is a PID-related function, not TID-related.

Maybe rather Dwfl_Frame_Callbacks, I no longer remember much why I called it
dwfl_frame_state and not just dwfl_frame.

> /* pid is the process id associated with the Dwfl state, arg is the
>    callback backend state.  Both will be provided to the callbacks.  */
> dwfl_attach_state (Dwfl *dwfl, pid_t pid,
>                    Dwfl_State_Callbacks *state, void *arg);
                     Dwfl_State_Callbacks *state_callbacks, void *arg);

> /* probably needed... */
> Dwfl *dwfl_thread_dwfl (Dwfl_Thread *thread);

> pid_t dwfl_thread_pid (Dwfl_Thread *thread);

PID or TID?  You have declared dwfl_thread_tid below.  But if it should be PID
then it should be:
> pid_t dwfl_pid (Dwfl *dwfl);

> typedef struct
> {
>   /* 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, 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.  */
>   bool (*set_initial_registers) (Dwfl_Thread *thread, pid_t tid,
>                                  void *arg);

I think it should integrate dwfl_thread_state_registers, all the
dwfl_thread_state_registers parameters should be here as return-references.

>   /* Called during unwinding to access memory (stack) state. */
>   bool (*memory_read) (Dwfl_Thread *thread, pid_t tid,
>                        Dwarf_Addr addr, Dwarf_Word *result,
>                        void *arg);
>   /* Called when unwinding is done. No callback will be called after
>      this has been called.  */
>   void (*thread_detach) (Dwfl_Thread *thread, pid_t tid, void *arg);
> } Dwfl_Thread_Callbacks;

> dwfl_thread_state (Dwfl_Thread *thread, Dwfl_Thread_Callbacks *state);

Proposing to be removed above.

> pid_t dwfl_thread_tid (Dwfl_Thread *thread);

> dwfl_thread_state_registers (Dwfl_Thread *thread,
>                              const int firstreg,
>                              unsigned nregs,
>                              const Dwarf_Word *regs);

I would delete this function, see above.  wrt its parameters:

This is apparently derived from dwfl_frame_state_data.  But I do not see what
is firstreg, where is pc/pc_set and where is regs_set.

PC_SET is true if PC contains a valid value.  On some archs PC is not present
in REGS. NREGS is number of valid registers in REGS and REGS_SET.  REGS_SET is
a bitfield specifying which REGS are valid.

extern Dwfl_Frame_State *dwfl_frame_state_data (Dwfl *dwfl, bool pc_set,
                                                Dwarf_Addr pc, unsigned nregs,
                                                const uint64_t *regs_set,
                                                const Dwarf_Addr *regs,
                                                void *memory_read_user_data);

> Then (the existing?) dwfl_linux_proc_report and dwfl_core_file_report
> could setup the above callbacks. Or they could be setup by someone by
> hand if they can provide registers and memory accessors in some other
> way.

Great idea.

> For the user/usage side we could then have:
> /* Gets the next known thread, if any.  To get the initial thread
>    provide NULL as previous thread.  */
> Dwfl_Thread *dwfl_next_thread (Dwfl *dwfl, Dwfl_Thread *pthread);
> /* 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_getdwarf (Dwfl_Thread *thread,
I do not understand the name "getdwarf".

> 		   int (*callback) (Dwfl_Frame *, void *),
                                    Dwfl_Frame_State *
Although maybe we could rename it to Dwfl_Frame anyway.

> 		   void *arg);
> bool dwfl_frame_state_pc (Dwfl_Frame_State *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]