2014-03-27 15:34:17 +00:00
|
|
|
#ifndef R2_DEBUG_H
|
|
|
|
#define R2_DEBUG_H
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
#include <r_types.h>
|
2010-02-04 12:23:53 +00:00
|
|
|
#include <r_anal.h>
|
2013-09-18 00:11:23 +00:00
|
|
|
#include <r_cons.h>
|
2009-02-05 21:08:46 +00:00
|
|
|
#include <r_util.h>
|
|
|
|
#include <r_reg.h>
|
2009-04-11 21:22:20 +00:00
|
|
|
#include <r_bp.h>
|
2013-09-18 00:11:23 +00:00
|
|
|
#include <r_db.h>
|
2009-09-10 20:51:34 +00:00
|
|
|
#include <r_io.h>
|
2009-02-05 21:08:46 +00:00
|
|
|
#include <r_syscall.h>
|
|
|
|
#include "list.h"
|
|
|
|
|
2014-10-30 21:58:51 +00:00
|
|
|
#include "r_bind.h"
|
2013-06-18 10:09:23 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2013-06-14 00:51:33 +00:00
|
|
|
R_LIB_VERSION_HEADER(r_debug);
|
|
|
|
|
2011-04-01 17:25:48 +00:00
|
|
|
/* hack to fix compilation of debugger on BSD systems */
|
|
|
|
/* This needs some testing (netbsd, freebsd, openbsd, kfreebsd) */
|
|
|
|
#if __BSD__
|
|
|
|
#include <machine/reg.h>
|
|
|
|
|
2011-07-22 09:29:58 +00:00
|
|
|
/* hakish hack to hack the openbsd/sparc64 hack */
|
|
|
|
#undef reg
|
|
|
|
#undef fpreg
|
|
|
|
#undef fpstate
|
|
|
|
#undef trapframe
|
|
|
|
#undef rwindow
|
|
|
|
|
2011-04-01 17:25:48 +00:00
|
|
|
#define PTRACE_PEEKTEXT PT_READ_I
|
|
|
|
#define PTRACE_POKETEXT PT_WRITE_I
|
|
|
|
#define PTRACE_PEEKDATA PT_READ_D
|
|
|
|
#define PTRACE_POKEDATA PT_WRITE_D
|
|
|
|
#define PTRACE_ATTACH PT_ATTACH
|
|
|
|
#define PTRACE_DETACH PT_DETACH
|
|
|
|
#define PTRACE_SINGLESTEP PT_STEP
|
|
|
|
#define PTRACE_CONT PT_CONTINUE
|
|
|
|
#define PTRACE_GETREGS PT_GETREGS
|
|
|
|
#define PTRACE_SETREGS PT_SETREGS
|
|
|
|
#define PTRACE_SYSCALL PT_STEP
|
|
|
|
#endif
|
|
|
|
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* states that a process can be in
|
|
|
|
*/
|
|
|
|
typedef enum {
|
2010-06-18 09:09:19 +00:00
|
|
|
R_DBG_PROC_STOP = 's',
|
|
|
|
R_DBG_PROC_RUN = 'r',
|
|
|
|
R_DBG_PROC_SLEEP = 'S',
|
2010-11-11 00:09:27 +00:00
|
|
|
R_DBG_PROC_ZOMBIE = 'z',
|
|
|
|
R_DBG_PROC_DEAD = 'd',
|
|
|
|
R_DBG_PROC_RAISED = 'R' // has produced a signal, breakpoint, etc..
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
} RDebugPidState;
|
2009-12-24 02:17:53 +00:00
|
|
|
|
2013-09-18 00:11:23 +00:00
|
|
|
|
2010-02-02 10:09:52 +00:00
|
|
|
// signal handling must support application and debugger level options
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
typedef enum {
|
|
|
|
R_DBG_SIGNAL_IGNORE = 0, // ignore signal handler
|
|
|
|
R_DBG_SIGNAL_CONT = 1, // pass signal to chlidren and continue execution
|
|
|
|
R_DBG_SIGNAL_SKIP = 2, //
|
2010-02-02 10:09:52 +00:00
|
|
|
//..
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
} RDebugSignalMode;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* when a user wants to resume from a breakpoint, we need to know how they want
|
|
|
|
* to proceed. these values indicate their intention.
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
R_DBG_RECOIL_NONE = 0,
|
|
|
|
R_DBG_RECOIL_STEP,
|
|
|
|
R_DBG_RECOIL_CONTINUE
|
|
|
|
} RDebugRecoilMode;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* List of reasons that an inferior might have stopped
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
R_DEBUG_REASON_DEAD = -1,
|
|
|
|
R_DEBUG_REASON_NONE = 0,
|
|
|
|
R_DEBUG_REASON_SIGNAL,
|
|
|
|
R_DEBUG_REASON_SEGFAULT,
|
|
|
|
R_DEBUG_REASON_BREAKPOINT,
|
2016-07-01 21:06:13 +00:00
|
|
|
R_DEBUG_REASON_TRACEPOINT,
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
R_DEBUG_REASON_READERR,
|
|
|
|
R_DEBUG_REASON_STEP,
|
|
|
|
R_DEBUG_REASON_ABORT,
|
|
|
|
R_DEBUG_REASON_WRITERR,
|
|
|
|
R_DEBUG_REASON_DIVBYZERO,
|
|
|
|
R_DEBUG_REASON_ILLEGAL,
|
|
|
|
R_DEBUG_REASON_UNKNOWN,
|
|
|
|
R_DEBUG_REASON_ERROR,
|
|
|
|
R_DEBUG_REASON_NEW_PID,
|
|
|
|
R_DEBUG_REASON_NEW_TID,
|
|
|
|
R_DEBUG_REASON_NEW_LIB,
|
|
|
|
R_DEBUG_REASON_EXIT_PID,
|
|
|
|
R_DEBUG_REASON_EXIT_TID,
|
|
|
|
R_DEBUG_REASON_EXIT_LIB,
|
|
|
|
R_DEBUG_REASON_TRAP,
|
|
|
|
R_DEBUG_REASON_SWI,
|
|
|
|
R_DEBUG_REASON_INT,
|
|
|
|
R_DEBUG_REASON_FPU,
|
|
|
|
} RDebugReasonType;
|
|
|
|
|
2010-02-02 10:09:52 +00:00
|
|
|
|
2010-03-01 09:49:04 +00:00
|
|
|
/* TODO: move to r_anal */
|
|
|
|
typedef struct r_debug_frame_t {
|
|
|
|
ut64 addr;
|
|
|
|
int size;
|
2015-10-22 10:38:57 +00:00
|
|
|
ut64 sp;
|
|
|
|
ut64 bp;
|
2010-03-01 09:49:04 +00:00
|
|
|
} RDebugFrame;
|
|
|
|
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
|
2015-08-16 22:12:54 +00:00
|
|
|
typedef struct r_debug_reason_t {
|
2016-06-22 17:43:19 +00:00
|
|
|
int /*RDebugReasonType*/ type;
|
2015-08-16 22:12:54 +00:00
|
|
|
int tid;
|
|
|
|
int signum;
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
ut64 bp_addr;
|
2015-08-16 22:12:54 +00:00
|
|
|
ut64 timestamp;
|
|
|
|
ut64 addr;
|
|
|
|
ut64 ptr;
|
|
|
|
} RDebugReason;
|
|
|
|
|
2010-02-04 12:23:53 +00:00
|
|
|
typedef struct r_debug_map_t {
|
|
|
|
char *name;
|
|
|
|
ut64 addr;
|
|
|
|
ut64 addr_end;
|
|
|
|
ut64 size;
|
|
|
|
char *file;
|
|
|
|
int perm;
|
|
|
|
int user;
|
|
|
|
} RDebugMap;
|
|
|
|
|
2013-08-29 02:44:18 +00:00
|
|
|
typedef struct r_debug_signal_t {
|
|
|
|
int type;
|
|
|
|
int num;
|
|
|
|
ut64 handler;
|
|
|
|
} RDebugSignal;
|
|
|
|
|
2011-07-25 02:49:54 +00:00
|
|
|
typedef struct r_debug_desc_t {
|
|
|
|
int fd;
|
|
|
|
char *path;
|
|
|
|
int perm;
|
|
|
|
int type;
|
|
|
|
ut64 off;
|
|
|
|
} RDebugDesc;
|
|
|
|
|
2015-02-23 02:29:40 +00:00
|
|
|
typedef struct r_debug_snap_t {
|
|
|
|
ut64 addr;
|
|
|
|
ut64 addr_end;
|
|
|
|
ut8 *data;
|
|
|
|
ut32 size;
|
|
|
|
ut64 timestamp;
|
|
|
|
ut32 crc;
|
|
|
|
char *comment;
|
|
|
|
} RDebugSnap;
|
|
|
|
|
2010-03-12 17:46:11 +00:00
|
|
|
typedef struct r_debug_trace_t {
|
2010-06-03 22:56:44 +00:00
|
|
|
RList *traces;
|
|
|
|
int count;
|
|
|
|
int enabled;
|
|
|
|
//int changed;
|
|
|
|
int tag;
|
|
|
|
int dup;
|
2010-06-13 09:59:17 +00:00
|
|
|
char *addresses;
|
2010-06-03 22:56:44 +00:00
|
|
|
// TODO: add range here
|
2014-11-02 00:21:45 +00:00
|
|
|
Sdb *db;
|
2010-06-03 22:56:44 +00:00
|
|
|
} RDebugTrace;
|
|
|
|
|
|
|
|
typedef struct r_debug_tracepoint_t {
|
2010-03-12 17:46:11 +00:00
|
|
|
ut64 addr;
|
2010-06-04 21:47:35 +00:00
|
|
|
ut64 tags; // XXX
|
|
|
|
int tag; // XXX
|
2010-03-12 17:46:11 +00:00
|
|
|
int size;
|
|
|
|
int count;
|
2010-06-03 22:56:44 +00:00
|
|
|
int times;
|
2010-03-12 17:46:11 +00:00
|
|
|
ut64 stamp;
|
2010-06-03 22:56:44 +00:00
|
|
|
} RDebugTracepoint;
|
|
|
|
|
2009-12-24 02:17:53 +00:00
|
|
|
typedef struct r_debug_t {
|
2015-10-22 01:11:03 +00:00
|
|
|
char *arch;
|
2011-05-05 22:59:10 +00:00
|
|
|
int bits; /// XXX: MUST SET ///
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
|
|
|
|
int pid; /* selected process id */
|
|
|
|
int tid; /* selected thread id */
|
|
|
|
int forked_pid; /* last pid created by fork */
|
|
|
|
RList *threads; /* NOTE: list contents are platform-specific */
|
|
|
|
|
|
|
|
/* dbg.* config options (see e?dbg)
|
|
|
|
* NOTE: some settings are checked inline instead of tracked here.
|
|
|
|
*/
|
|
|
|
int bpsize; /* size of a breakpoint */
|
|
|
|
char *btalgo; /* select backtrace algorithm */
|
|
|
|
int btdepth; /* backtrace depth */
|
|
|
|
int regcols; /* display columns */
|
2009-09-20 00:16:14 +00:00
|
|
|
int swstep; /* steps with software traps */
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
int stop_all_threads; /* stop all threads at any stop */
|
|
|
|
int trace_forks; /* stop on new children */
|
|
|
|
int trace_execs; /* stop on new execs */
|
|
|
|
int trace_clone; /* stop on new threads */
|
|
|
|
char *glob_libs; /* stop on lib load */
|
|
|
|
char *glob_unlibs; /* stop on lib unload */
|
|
|
|
|
|
|
|
/* tracking debugger state */
|
|
|
|
int steps; /* counter of steps done */
|
2015-08-16 22:12:54 +00:00
|
|
|
RDebugReason reason; /* stop reason */
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
RDebugRecoilMode recoil_mode; /* what did the user want to do? */
|
|
|
|
|
|
|
|
/* tracing vars */
|
2010-06-03 22:56:44 +00:00
|
|
|
RDebugTrace *trace;
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
Sdb *tracenodes;
|
|
|
|
RTree *tree;
|
|
|
|
|
2013-05-20 01:00:49 +00:00
|
|
|
RReg *reg;
|
2016-02-25 10:35:59 +00:00
|
|
|
const char *creg; // current register value
|
2010-06-29 23:13:09 +00:00
|
|
|
RBreakpoint *bp;
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
void *user; // XXX(jjd): unused?? meant for caller's use??
|
|
|
|
|
2009-09-20 00:16:14 +00:00
|
|
|
/* io */
|
2015-08-08 18:15:13 +00:00
|
|
|
PrintfCallback cb_printf;
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
RIOBind iob;
|
|
|
|
|
2010-05-25 23:42:22 +00:00
|
|
|
struct r_debug_plugin_t *h;
|
2010-05-26 16:25:35 +00:00
|
|
|
struct list_head plugins;
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
|
2010-05-24 10:07:54 +00:00
|
|
|
RAnal *anal;
|
2010-02-04 12:23:53 +00:00
|
|
|
RList *maps; // <RDebugMap>
|
|
|
|
RList *maps_user; // <RDebugMap>
|
2015-02-23 02:29:40 +00:00
|
|
|
RList *snaps; // <RDebugSnap>
|
2014-03-24 23:34:23 +00:00
|
|
|
Sdb *sgnls;
|
2014-10-30 21:58:51 +00:00
|
|
|
RCoreBind corebind;
|
2014-12-11 23:34:53 +00:00
|
|
|
// internal use only
|
|
|
|
int _mode;
|
2015-07-21 04:06:00 +00:00
|
|
|
RNum *num;
|
2010-01-26 00:28:33 +00:00
|
|
|
} RDebug;
|
2009-09-20 00:16:14 +00:00
|
|
|
|
2010-06-18 09:09:19 +00:00
|
|
|
typedef struct r_debug_desc_plugin_t {
|
|
|
|
int (*open)(const char *path);
|
|
|
|
int (*close)(int fd);
|
|
|
|
int (*read)(int fd, ut64 addr, int len);
|
|
|
|
int (*write)(int fd, ut64 addr, int len);
|
|
|
|
int (*seek)(int fd, ut64 addr);
|
|
|
|
int (*dup)(int fd, int newfd);
|
2011-07-25 02:49:54 +00:00
|
|
|
RList* (*list)(int pid);
|
2010-06-18 09:09:19 +00:00
|
|
|
} RDebugDescPlugin;
|
|
|
|
|
2014-06-04 02:12:11 +00:00
|
|
|
typedef struct r_debug_info_t {
|
|
|
|
int pid;
|
|
|
|
int tid;
|
|
|
|
int uid;
|
|
|
|
int gid;
|
|
|
|
char *exe;
|
|
|
|
char *cmdline;
|
2015-10-12 16:49:16 +00:00
|
|
|
char *libname;
|
2014-06-04 02:12:11 +00:00
|
|
|
char *cwd;
|
|
|
|
int status; // zombie, running, sleeping, ...
|
2015-10-13 00:18:14 +00:00
|
|
|
int signum;
|
|
|
|
void * lib;
|
2014-06-04 02:12:11 +00:00
|
|
|
// retrieve mem/fd/core limits?
|
|
|
|
// list of threads ? hasthreads? counter?
|
|
|
|
// environment?
|
|
|
|
// /proc/pid/stack ???
|
|
|
|
// /proc/pid/syscall ???
|
2015-08-29 12:01:38 +00:00
|
|
|
//
|
2014-06-04 02:12:11 +00:00
|
|
|
} RDebugInfo;
|
|
|
|
|
2009-02-05 21:08:46 +00:00
|
|
|
/* TODO: pass dbg and user data pointer everywhere */
|
2010-05-25 23:42:22 +00:00
|
|
|
typedef struct r_debug_plugin_t {
|
2009-02-05 21:08:46 +00:00
|
|
|
const char *name;
|
2013-12-10 03:19:04 +00:00
|
|
|
const char *license;
|
2011-04-03 14:38:24 +00:00
|
|
|
//const char **archs; // MUST BE DEPREACTED!!!!
|
2010-03-03 13:48:17 +00:00
|
|
|
ut32 bits;
|
2015-10-22 01:11:03 +00:00
|
|
|
const char *arch;
|
2012-07-05 16:02:12 +00:00
|
|
|
int canstep;
|
2015-08-24 14:44:09 +00:00
|
|
|
int keepio;
|
2009-09-15 11:24:28 +00:00
|
|
|
/* life */
|
2014-06-04 02:12:11 +00:00
|
|
|
RDebugInfo* (*info)(RDebug *dbg, const char *arg);
|
2009-08-22 01:54:24 +00:00
|
|
|
int (*startv)(int argc, char **argv);
|
2011-05-05 22:59:10 +00:00
|
|
|
int (*attach)(RDebug *dbg, int pid);
|
2016-01-22 09:53:58 +00:00
|
|
|
int (*detach)(RDebug *dbg, int pid);
|
2010-02-02 10:09:52 +00:00
|
|
|
int (*select)(int pid, int tid);
|
2012-06-07 01:41:21 +00:00
|
|
|
RList *(*threads)(RDebug *dbg, int pid);
|
2010-03-05 00:49:12 +00:00
|
|
|
RList *(*pids)(int pid);
|
2011-05-01 02:00:59 +00:00
|
|
|
RList *(*tids)(int pid);
|
2010-02-12 10:45:22 +00:00
|
|
|
RFList (*backtrace)(int count);
|
2009-09-15 11:24:28 +00:00
|
|
|
/* flow */
|
2011-10-20 16:04:26 +00:00
|
|
|
int (*stop)(RDebug *dbg);
|
2010-11-17 01:31:56 +00:00
|
|
|
int (*step)(RDebug *dbg);
|
2011-10-09 02:15:32 +00:00
|
|
|
int (*step_over)(RDebug *dbg);
|
2011-04-03 14:38:24 +00:00
|
|
|
int (*cont)(RDebug *dbg, int pid, int tid, int sig);
|
2011-07-06 09:48:16 +00:00
|
|
|
int (*wait)(RDebug *dbg, int pid);
|
2016-03-24 19:22:50 +00:00
|
|
|
bool (*gcore)(RDebug *dbg, RBuffer *dest);
|
2012-12-07 11:03:53 +00:00
|
|
|
int (*kill)(RDebug *dbg, int pid, int tid, int sig);
|
2013-08-29 02:44:18 +00:00
|
|
|
RList* (*kill_list)(RDebug *dbg);
|
2011-04-03 14:38:24 +00:00
|
|
|
int (*contsc)(RDebug *dbg, int pid, int sc);
|
2012-06-14 00:18:15 +00:00
|
|
|
RList* (*frames)(RDebug *dbg, ut64 at);
|
2010-09-24 03:41:54 +00:00
|
|
|
RBreakpointCallback breakpoint;
|
2010-11-16 23:56:48 +00:00
|
|
|
// XXX: specify, pid, tid, or RDebug ?
|
2011-10-09 02:15:32 +00:00
|
|
|
int (*reg_read)(RDebug *dbg, int type, ut8 *buf, int size);
|
|
|
|
int (*reg_write)(RDebug *dbg, int type, const ut8 *buf, int size); //XXX struct r_regset_t regs);
|
2011-05-07 16:19:16 +00:00
|
|
|
char* (*reg_profile)(RDebug *dbg);
|
2009-09-15 11:24:28 +00:00
|
|
|
/* memory */
|
2010-02-04 12:23:53 +00:00
|
|
|
RList *(*map_get)(RDebug *dbg);
|
2015-08-23 23:27:29 +00:00
|
|
|
RList *(*modules_get)(RDebug *dbg);
|
2013-07-21 01:05:56 +00:00
|
|
|
RDebugMap* (*map_alloc)(RDebug *dbg, ut64 addr, int size);
|
|
|
|
int (*map_dealloc)(RDebug *dbg, ut64 addr, int size);
|
2011-11-25 03:32:32 +00:00
|
|
|
int (*map_protect)(RDebug *dbg, ut64 addr, int size, int perms);
|
2010-03-05 00:49:12 +00:00
|
|
|
int (*init)(RDebug *dbg);
|
2014-01-28 03:03:35 +00:00
|
|
|
int (*drx)(RDebug *dbg, int n, ut64 addr, int size, int rwx, int g);
|
2010-06-18 09:09:19 +00:00
|
|
|
RDebugDescPlugin desc;
|
|
|
|
// TODO: use RList here
|
2009-02-05 21:08:46 +00:00
|
|
|
struct list_head list;
|
2010-05-25 23:42:22 +00:00
|
|
|
} RDebugPlugin;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2009-12-24 02:17:53 +00:00
|
|
|
// TODO: rename to r_debug_process_t ? maybe a thread too ?
|
|
|
|
typedef struct r_debug_pid_t {
|
2009-04-01 22:44:43 +00:00
|
|
|
int pid;
|
2010-03-05 00:49:12 +00:00
|
|
|
char status; /* stopped, running, zombie, sleeping ,... */
|
2009-04-01 22:44:43 +00:00
|
|
|
int runnable; /* when using 'run', 'continue', .. this proc will be runnable */
|
2015-09-01 21:24:11 +00:00
|
|
|
char *path;
|
2010-11-11 00:09:27 +00:00
|
|
|
ut64 pc;
|
2010-01-26 00:28:33 +00:00
|
|
|
} RDebugPid;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
/*
|
|
|
|
* Radare's debugger has both an external and internal API.
|
|
|
|
*
|
|
|
|
* TODO(jjd): reconcile external API and extend it for better funcitonality
|
|
|
|
* when using R2 as a library.
|
|
|
|
*/
|
2009-12-24 02:17:53 +00:00
|
|
|
#ifdef R_API
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
R_API RDebug *r_debug_new(int hard);
|
|
|
|
R_API RDebug *r_debug_free(RDebug *dbg);
|
|
|
|
|
2012-07-21 10:11:21 +00:00
|
|
|
R_API int r_debug_attach(RDebug *dbg, int pid);
|
|
|
|
R_API int r_debug_detach(RDebug *dbg, int pid);
|
|
|
|
R_API int r_debug_startv(RDebug *dbg, int argc, char **argv);
|
|
|
|
R_API int r_debug_start(RDebug *dbg, const char *cmd);
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
|
|
|
|
/* reason we stopped */
|
|
|
|
R_API RDebugReasonType r_debug_stop_reason(RDebug *dbg);
|
2015-08-16 22:12:54 +00:00
|
|
|
R_API const char *r_debug_reason_to_string(int type);
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
|
|
|
|
/* wait for another event */
|
|
|
|
R_API RDebugReasonType r_debug_wait(RDebug *dbg);
|
|
|
|
|
|
|
|
/* continuations */
|
|
|
|
R_API int r_debug_step(RDebug *dbg, int steps);
|
2012-07-21 10:11:21 +00:00
|
|
|
R_API int r_debug_step_over(RDebug *dbg, int steps);
|
|
|
|
R_API int r_debug_continue_until(RDebug *dbg, ut64 addr);
|
2010-05-24 15:51:51 +00:00
|
|
|
R_API int r_debug_continue_until_optype(RDebug *dbg, int type, int over);
|
2010-06-03 22:56:44 +00:00
|
|
|
R_API int r_debug_continue_until_nontraced(RDebug *dbg);
|
2012-07-21 10:11:21 +00:00
|
|
|
R_API int r_debug_continue_syscall(RDebug *dbg, int sc);
|
2014-06-14 00:09:41 +00:00
|
|
|
R_API int r_debug_continue_syscalls(RDebug *dbg, int *sc, int n_sc);
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
R_API int r_debug_continue(RDebug *dbg);
|
|
|
|
R_API int r_debug_continue_kill(RDebug *dbg, int signal);
|
|
|
|
|
|
|
|
/* process/thread handling */
|
|
|
|
R_API int r_debug_select(RDebug *dbg, int pid, int tid);
|
2012-07-21 10:11:21 +00:00
|
|
|
//R_API int r_debug_pid_add(RDebug *dbg);
|
|
|
|
//R_API int r_debug_pid_add_thread(RDebug *dbg);
|
|
|
|
//R_API int r_debug_pid_del(RDebug *dbg);
|
|
|
|
//R_API int r_debug_pid_del_thread(RDebug *dbg);
|
2014-10-01 19:39:28 +00:00
|
|
|
R_API int r_debug_pid_list(RDebug *dbg, int pid, char fmt);
|
2011-02-04 17:34:20 +00:00
|
|
|
R_API RDebugPid *r_debug_pid_new(const char *path, int pid, char status, ut64 pc);
|
2010-10-27 22:55:07 +00:00
|
|
|
R_API RDebugPid *r_debug_pid_free(RDebugPid *pid);
|
2011-02-11 16:29:31 +00:00
|
|
|
R_API RList *r_debug_pids(RDebug *dbg, int pid);
|
2010-02-11 23:43:11 +00:00
|
|
|
|
2015-12-04 01:57:56 +00:00
|
|
|
R_API bool r_debug_set_arch(RDebug *dbg, const char *arch, int bits);
|
|
|
|
R_API bool r_debug_use(RDebug *dbg, const char *str);
|
2009-09-20 00:16:14 +00:00
|
|
|
|
2014-06-04 02:12:11 +00:00
|
|
|
R_API RDebugInfo *r_debug_info(RDebug *dbg, const char *arg);
|
|
|
|
R_API void r_debug_info_free (RDebugInfo *rdi);
|
|
|
|
|
2009-04-01 22:44:43 +00:00
|
|
|
/* send signals */
|
2013-09-18 00:11:23 +00:00
|
|
|
R_API void r_debug_signal_init(RDebug *dbg);
|
|
|
|
R_API int r_debug_signal_send(RDebug *dbg, int num);
|
|
|
|
R_API int r_debug_signal_what(RDebug *dbg, int num);
|
|
|
|
R_API int r_debug_signal_resolve(RDebug *dbg, const char *signame);
|
|
|
|
R_API const char *r_debug_signal_resolve_i(RDebug *dbg, int signum);
|
|
|
|
R_API void r_debug_signal_setup(RDebug *dbg, int num, int opt);
|
|
|
|
R_API int r_debug_signal_set(RDebug *dbg, int num, ut64 addr);
|
2014-12-11 23:34:53 +00:00
|
|
|
R_API void r_debug_signal_list(RDebug *dbg, int mode);
|
2012-12-07 11:03:53 +00:00
|
|
|
R_API int r_debug_kill(RDebug *dbg, int pid, int tid, int sig);
|
2013-08-29 02:44:18 +00:00
|
|
|
R_API RList *r_debug_kill_list(RDebug *dbg);
|
2010-10-27 22:55:07 +00:00
|
|
|
// XXX: must be uint64 action
|
2012-07-21 10:11:21 +00:00
|
|
|
R_API int r_debug_kill_setup(RDebug *dbg, int sig, int action);
|
2009-08-14 00:37:18 +00:00
|
|
|
|
2009-03-06 00:00:41 +00:00
|
|
|
/* handle.c */
|
2015-12-04 01:57:56 +00:00
|
|
|
R_API void r_debug_plugin_init(RDebug *dbg);
|
2012-07-21 10:11:21 +00:00
|
|
|
R_API int r_debug_plugin_set(RDebug *dbg, const char *str);
|
|
|
|
R_API int r_debug_plugin_list(RDebug *dbg);
|
2015-12-04 01:57:56 +00:00
|
|
|
R_API bool r_debug_plugin_add(RDebug *dbg, RDebugPlugin *foo);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2009-09-17 09:48:36 +00:00
|
|
|
/* memory */
|
2015-08-23 23:27:29 +00:00
|
|
|
R_API RList *r_debug_modules_list(RDebug*);
|
2013-07-21 01:05:56 +00:00
|
|
|
R_API RDebugMap *r_debug_map_alloc(RDebug *dbg, ut64 addr, int size);
|
2010-02-04 12:23:53 +00:00
|
|
|
R_API int r_debug_map_dealloc(RDebug *dbg, RDebugMap *map);
|
2015-01-13 02:40:01 +00:00
|
|
|
R_API RList *r_debug_map_list_new(void);
|
2010-02-04 12:23:53 +00:00
|
|
|
R_API RDebugMap *r_debug_map_get(RDebug *dbg, ut64 addr);
|
|
|
|
R_API RDebugMap *r_debug_map_new (char *name, ut64 addr, ut64 addr_end, int perm, int user);
|
|
|
|
R_API void r_debug_map_free(RDebugMap *map);
|
2011-10-09 17:45:34 +00:00
|
|
|
R_API void r_debug_map_list(RDebug *dbg, ut64 addr, int rad);
|
2016-06-06 15:30:07 +00:00
|
|
|
R_API void r_debug_map_list_visual(RDebug *dbg, ut64 addr, int use_color, int cons_cols);
|
2009-04-16 20:49:18 +00:00
|
|
|
|
2010-06-18 09:09:19 +00:00
|
|
|
/* descriptors */
|
2011-07-25 02:49:54 +00:00
|
|
|
R_API RDebugDesc *r_debug_desc_new (int fd, char* path, int perm, int type, int off);
|
|
|
|
R_API void r_debug_desc_free (RDebugDesc *p);
|
2010-06-18 09:09:19 +00:00
|
|
|
R_API int r_debug_desc_open(RDebug *dbg, const char *path);
|
|
|
|
R_API int r_debug_desc_close(RDebug *dbg, int fd);
|
|
|
|
R_API int r_debug_desc_dup(RDebug *dbg, int fd, int newfd);
|
|
|
|
R_API int r_debug_desc_read(RDebug *dbg, int fd, ut64 addr, int len);
|
2010-10-27 22:55:07 +00:00
|
|
|
R_API int r_debug_desc_seek(RDebug *dbg, int fd, ut64 addr); // TODO: whence?
|
2010-06-18 09:09:19 +00:00
|
|
|
R_API int r_debug_desc_write(RDebug *dbg, int fd, ut64 addr, int len);
|
|
|
|
R_API int r_debug_desc_list(RDebug *dbg, int rad);
|
|
|
|
|
2009-04-16 20:49:18 +00:00
|
|
|
/* registers */
|
2010-10-27 22:55:07 +00:00
|
|
|
R_API int r_debug_reg_sync(RDebug *dbg, int type, int write);
|
2014-06-04 15:23:58 +00:00
|
|
|
R_API int r_debug_reg_list(RDebug *dbg, int type, int size, int rad, const char *use_color);
|
2010-10-27 22:55:07 +00:00
|
|
|
R_API int r_debug_reg_set(RDebug *dbg, const char *name, ut64 num);
|
|
|
|
R_API ut64 r_debug_reg_get(RDebug *dbg, const char *name);
|
2014-11-20 00:30:37 +00:00
|
|
|
R_API ut64 r_debug_reg_get_err(RDebug *dbg, const char *name, int *err);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
|
|
|
R_API void r_debug_io_bind(RDebug *dbg, RIO *io);
|
2013-04-16 02:01:39 +00:00
|
|
|
R_API ut64 r_debug_execute(RDebug *dbg, const ut8 *buf, int len, int restore);
|
2010-02-05 11:21:37 +00:00
|
|
|
R_API int r_debug_map_sync(RDebug *dbg);
|
2010-03-02 10:18:49 +00:00
|
|
|
|
2011-10-20 16:04:26 +00:00
|
|
|
R_API int r_debug_stop(RDebug *dbg);
|
|
|
|
|
2010-03-02 10:18:49 +00:00
|
|
|
/* backtrace */
|
2016-01-29 23:52:53 +00:00
|
|
|
R_API RList *r_debug_frames(RDebug *dbg, ut64 at);
|
2010-03-04 00:46:25 +00:00
|
|
|
|
2016-01-29 23:52:53 +00:00
|
|
|
R_API int r_debug_is_dead(RDebug *dbg);
|
|
|
|
R_API int r_debug_map_protect(RDebug *dbg, ut64 addr, int size, int perms);
|
2010-06-03 22:56:44 +00:00
|
|
|
/* args XXX: weird food */
|
2016-01-29 23:52:53 +00:00
|
|
|
R_API ut64 r_debug_arg_get(RDebug *dbg, int fast, int num);
|
|
|
|
R_API bool r_debug_arg_set(RDebug *dbg, int fast, int num, ut64 value);
|
2010-03-11 00:04:59 +00:00
|
|
|
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
/* breakpoints (most in r_bp, this calls those) */
|
2016-05-15 23:00:11 +00:00
|
|
|
R_API RBreakpointItem *r_debug_bp_add(RDebug *dbg, ut64 addr, int hw, char *module, st64 m_delta);
|
|
|
|
|
2010-03-11 00:04:59 +00:00
|
|
|
/* pid */
|
2012-07-21 10:11:21 +00:00
|
|
|
R_API int r_debug_thread_list(RDebug *dbg, int pid);
|
2010-03-12 17:46:11 +00:00
|
|
|
|
2016-01-29 23:52:53 +00:00
|
|
|
R_API void r_debug_tracenodes_reset(RDebug *dbg);
|
2015-06-08 22:47:13 +00:00
|
|
|
|
2016-01-29 23:52:53 +00:00
|
|
|
R_API void r_debug_trace_reset(RDebug *dbg);
|
Major rework to the native debugger (esp on Linux) (#5185)
The major contribution here is completely re-worked breakpoint hit/recoil
handling. This work fixes #4907 and lays the ground work for future native
debugger improvements (multi-threading, etc).
* Give a human friendly type to enums
* Change many wait functions to return RDebugReasonType
* Better return checking (from r_debug_reg_sync, r_bp_restore)
* Optimized register synchronization
* Lots of comments and whitespace changes
* Improved inferior death detection
Handle EXIT_PID events differently than DEAD process events
* Move breakpoint/recoil handling to wait/cont/step
Rather than handing breakpoint related things inside cmd_debug.c, do that
inside the r_debug API functions. This seems like the most logical place for it
to live since it should apply to just about any platform/architecture. This
also centralizes calling into "cmd.bp" handling via the CoreBind callback.
* Track how the caller wishes to continue
It turns out that handling break point recoils is very complicated. The ptrace
API on Linux returns SIGTRAP for just about every type of operation (not just
breakpoints getting hit). Add the "recoil_mode" flag to indicate whether we are
single-stepping or continuing and whether or not we are inside the recoil.
* Proper handling for swstep=true
Since r_debug_step_soft calls r_debug_continue, it's already hitting the recoil
case there. Move the recoil handling from r_debug_step to r_debug_step_hard
only.
For the swstep=true case, special handling is required inside r_debug_recoil.
By resetting all of the breakpoints except the one we just hit, we ensure we
can step the original instruction and hit the new swstep breakpoint. Add a new
bp function called r_bp_restore_except to do this.
To make matters worse, we cannot use a BreakpointItem pointer because that
leads to a use-after-free condition. Instead, we the breakpoint address
instead.
Now breakpoints should work regardless of the swtep setting.
* Always call the recoil before continuing
Some callers of r_debug_continue might not have ever inserted any breakpoints
before. If we don't restore breakpoints before each call to the underlying
continue we won't hit them.
* Hide software step breakpoint events from the user
When a breakpoint even happens due to a software-step, hide it from the user.
They aren't really breakpoints as far as they are concerned.
* Improve process exit handling on Linux
There are three types of process exiting events on Linux:
1. PTRACE_EVENT_EXIT occurs just before a process exits. It's not possible to
prevent it from exiting, but it can be used to inspect the pre-exit state.
2. The process can exit for a variety of reasons and we can notice when we call
waitpid(2).
3. The process could die randomly on us :-/
On Windows, h->wait will return R_DEBUG_REASON_EXIT_PID, but it's more likely
on Linux to find out the process is already dead.
* Check more bits within waitpid status
We can often make a decision about what happened strictly by looking at the
status returned from waitpid. In other cases, we need to call
r_debug_handle_signals.
If we reach the end of this function without knowing what happened, consider it
an error.
2016-06-22 08:34:45 +00:00
|
|
|
R_API int r_debug_trace_pc(RDebug *dbg, ut64 pc);
|
2016-01-29 23:52:53 +00:00
|
|
|
R_API void r_debug_trace_at(RDebug *dbg, const char *str);
|
|
|
|
R_API RDebugTracepoint *r_debug_trace_get(RDebug *dbg, ut64 addr);
|
|
|
|
R_API void r_debug_trace_list(RDebug *dbg, int mode);
|
|
|
|
R_API RDebugTracepoint *r_debug_trace_add(RDebug *dbg, ut64 addr, int size);
|
|
|
|
R_API RDebugTrace *r_debug_trace_new(void);
|
2016-06-01 10:23:10 +00:00
|
|
|
R_API void r_debug_trace_free(RDebugTrace *dbg);
|
2016-01-29 23:52:53 +00:00
|
|
|
R_API int r_debug_trace_tag(RDebug *dbg, int tag);
|
|
|
|
R_API int r_debug_child_fork(RDebug *dbg);
|
|
|
|
R_API int r_debug_child_clone(RDebug *dbg);
|
2010-03-12 17:46:11 +00:00
|
|
|
|
2016-01-29 23:52:53 +00:00
|
|
|
R_API void r_debug_drx_list(RDebug *dbg);
|
|
|
|
R_API int r_debug_drx_set(RDebug *dbg, int idx, ut64 addr, int len, int rwx, int g);
|
|
|
|
R_API int r_debug_drx_unset(RDebug *dbg, int idx);
|
2014-01-28 03:38:02 +00:00
|
|
|
|
2015-07-21 04:06:00 +00:00
|
|
|
/* esil */
|
|
|
|
R_API ut64 r_debug_num_callback(RNum *userptr, const char *str, int *ok);
|
2016-01-29 23:52:53 +00:00
|
|
|
R_API int r_debug_esil_stepi(RDebug *dbg);
|
|
|
|
R_API ut64 r_debug_esil_step(RDebug *dbg, ut32 count);
|
|
|
|
R_API ut64 r_debug_esil_continue(RDebug *dbg);
|
2015-07-21 04:06:00 +00:00
|
|
|
R_API void r_debug_esil_watch(RDebug *dbg, int rwx, int dev, const char *expr);
|
|
|
|
R_API void r_debug_esil_watch_reset(RDebug *dbg);
|
|
|
|
R_API void r_debug_esil_watch_list(RDebug *dbg);
|
|
|
|
R_API int r_debug_esil_watch_empty(RDebug *dbg);
|
|
|
|
R_API void r_debug_esil_prestep (RDebug *d, int p);
|
|
|
|
|
2015-02-23 02:29:40 +00:00
|
|
|
/* snap */
|
2016-01-29 23:52:53 +00:00
|
|
|
R_API void r_debug_snap_free(void *snap);
|
2015-02-23 02:29:40 +00:00
|
|
|
R_API int r_debug_snap_delete(RDebug *dbg, int idx);
|
2015-07-22 22:49:59 +00:00
|
|
|
R_API void r_debug_snap_list(RDebug *dbg, int idx, int mode);
|
2015-02-23 02:29:40 +00:00
|
|
|
R_API int r_debug_snap_diff(RDebug *dbg, int idx);
|
|
|
|
R_API int r_debug_snap(RDebug *dbg, ut64 addr);
|
|
|
|
R_API int r_debug_snap_comment (RDebug *dbg, int idx, const char *msg);
|
2015-07-22 22:49:59 +00:00
|
|
|
R_API int r_debug_snap_all(RDebug *dbg, int perms);
|
2015-08-19 12:06:59 +00:00
|
|
|
R_API RDebugSnap* r_debug_snap_get (RDebug *dbg, ut64 addr);
|
2015-02-23 02:29:40 +00:00
|
|
|
|
2013-05-20 01:00:49 +00:00
|
|
|
/* plugin pointers */
|
|
|
|
extern RDebugPlugin r_debug_plugin_native;
|
|
|
|
extern RDebugPlugin r_debug_plugin_esil;
|
|
|
|
extern RDebugPlugin r_debug_plugin_rap;
|
|
|
|
extern RDebugPlugin r_debug_plugin_gdb;
|
|
|
|
extern RDebugPlugin r_debug_plugin_bf;
|
2014-08-31 16:09:25 +00:00
|
|
|
extern RDebugPlugin r_debug_plugin_wind;
|
2016-02-24 09:15:08 +00:00
|
|
|
extern RDebugPlugin r_debug_plugin_bochs;
|
2016-04-17 20:38:04 +00:00
|
|
|
extern RDebugPlugin r_debug_plugin_qnx;
|
2009-09-22 11:27:33 +00:00
|
|
|
#endif
|
2013-06-18 10:09:23 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-12-24 02:17:53 +00:00
|
|
|
#endif
|
2009-04-16 20:49:18 +00:00
|
|
|
|
|
|
|
/* regset */
|
2009-09-22 11:27:33 +00:00
|
|
|
//R_API struct r_regset_t* r_regset_diff(struct r_regset_t *a, struct r_regset_t *b);
|
|
|
|
//R_API int r_regset_set(struct r_regset_t *r, int idx, const char *name, ut64 value);
|
|
|
|
//R_API struct r_regset_t *r_regset_new(int size);
|
|
|
|
//R_API void r_regset_free(struct r_regset_t *r);
|
2009-08-14 00:37:18 +00:00
|
|
|
|
2009-02-05 21:08:46 +00:00
|
|
|
#if 0
|
|
|
|
Missing callbacks
|
|
|
|
=================
|
|
|
|
- alloc
|
|
|
|
- dealloc
|
2010-02-02 10:09:52 +00:00
|
|
|
- list maps (memory regions)
|
2009-02-05 21:08:46 +00:00
|
|
|
- change memory protections
|
|
|
|
- touchtrace
|
|
|
|
- filedescriptor set/get/mod..
|
|
|
|
- get/set signals
|
|
|
|
- get regs, set regs
|
|
|
|
|
|
|
|
#endif
|