* Various modifications needed due to the changes in <debugger.h>.
* user_debug_break_or_watchpoint_hit() into separate functions for break- and watchpoints. The one for breakpoints gets another parameter which indicates whether the breakpoint was a soft- or hardware breakpoint. This info is also sent to the debugger. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11714 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -95,8 +95,8 @@ enum {
|
|||||||
// messages sent from the debug nub thread to a debugged thread
|
// messages sent from the debug nub thread to a debugged thread
|
||||||
typedef enum {
|
typedef enum {
|
||||||
B_DEBUGGED_THREAD_MESSAGE_CONTINUE = 0,
|
B_DEBUGGED_THREAD_MESSAGE_CONTINUE = 0,
|
||||||
B_DEBUGGED_THREAD_GET_WHY_STOPPED,
|
|
||||||
B_DEBUGGED_THREAD_SET_CPU_STATE,
|
B_DEBUGGED_THREAD_SET_CPU_STATE,
|
||||||
|
B_DEBUGGED_THREAD_GET_CPU_STATE,
|
||||||
B_DEBUGGED_THREAD_DEBUGGER_CHANGED,
|
B_DEBUGGED_THREAD_DEBUGGER_CHANGED,
|
||||||
} debugged_thread_message;
|
} debugged_thread_message;
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
port_id reply_port;
|
port_id reply_port;
|
||||||
} debugged_thread_get_why_stopped;
|
} debugged_thread_get_cpu_state;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
debug_cpu_state cpu_state;
|
debug_cpu_state cpu_state;
|
||||||
@@ -115,8 +115,8 @@ typedef struct {
|
|||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
debugged_thread_continue continue_thread;
|
debugged_thread_continue continue_thread;
|
||||||
debugged_thread_get_why_stopped get_why_stopped;
|
|
||||||
debugged_thread_set_cpu_state set_cpu_state;
|
debugged_thread_set_cpu_state set_cpu_state;
|
||||||
|
debugged_thread_get_cpu_state get_cpu_state;
|
||||||
} debugged_thread_message_data;
|
} debugged_thread_message_data;
|
||||||
|
|
||||||
|
|
||||||
@@ -155,7 +155,8 @@ void user_debug_thread_created(thread_id threadID);
|
|||||||
void user_debug_thread_deleted(team_id teamID, thread_id threadID);
|
void user_debug_thread_deleted(team_id teamID, thread_id threadID);
|
||||||
void user_debug_image_created(const image_info *imageInfo);
|
void user_debug_image_created(const image_info *imageInfo);
|
||||||
void user_debug_image_deleted(const image_info *imageInfo);
|
void user_debug_image_deleted(const image_info *imageInfo);
|
||||||
void user_debug_break_or_watchpoint_hit(bool watchpoint);
|
void user_debug_breakpoint_hit(bool software);
|
||||||
|
void user_debug_watchpoint_hit();
|
||||||
void user_debug_single_stepped();
|
void user_debug_single_stepped();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+220
-162
@@ -19,7 +19,7 @@
|
|||||||
#include <user_debugger.h>
|
#include <user_debugger.h>
|
||||||
#include <arch/user_debugger.h>
|
#include <arch/user_debugger.h>
|
||||||
|
|
||||||
#define TRACE_USER_DEBUGGER
|
//#define TRACE_USER_DEBUGGER
|
||||||
#ifdef TRACE_USER_DEBUGGER
|
#ifdef TRACE_USER_DEBUGGER
|
||||||
# define TRACE(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
#else
|
#else
|
||||||
@@ -220,31 +220,15 @@ get_team_debug_info(team_debug_info &teamDebugInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
prepare_thread_stopped_message(debug_thread_stopped &message,
|
|
||||||
debug_why_stopped whyStopped, port_id nubPort, void *data)
|
|
||||||
{
|
|
||||||
struct thread *thread = thread_get_current_thread();
|
|
||||||
|
|
||||||
message.origin.thread = thread->id;
|
|
||||||
message.origin.team = thread->team->id;
|
|
||||||
message.origin.nub_port = nubPort;
|
|
||||||
message.why = whyStopped;
|
|
||||||
message.data = data;
|
|
||||||
arch_get_debug_cpu_state(&message.cpu_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
thread_hit_debug_event_internal(uint32 event, const void *message, int32 size,
|
thread_hit_debug_event_internal(debug_debugger_message event,
|
||||||
debug_why_stopped whyStopped, void *additionalData, bool requireDebugger,
|
const void *message, int32 size, bool requireDebugger, bool &restart)
|
||||||
bool &restart)
|
|
||||||
{
|
{
|
||||||
restart = false;
|
restart = false;
|
||||||
struct thread *thread = thread_get_current_thread();
|
struct thread *thread = thread_get_current_thread();
|
||||||
|
|
||||||
TRACE(("thread_hit_debug_event(): thread: %ld, event: %lu, message: %p, "
|
TRACE(("thread_hit_debug_event(): thread: %ld, event: %lu, message: %p, "
|
||||||
"size: %ld\n", thread->id, event, message, size));
|
"size: %ld\n", thread->id, (uint32)event, message, size));
|
||||||
|
|
||||||
// check, if there's a debug port already
|
// check, if there's a debug port already
|
||||||
bool setPort = !(atomic_get(&thread->debug_info.flags)
|
bool setPort = !(atomic_get(&thread->debug_info.flags)
|
||||||
@@ -364,23 +348,6 @@ thread_hit_debug_event_internal(uint32 event, const void *message, int32 size,
|
|||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_DEBUGGED_THREAD_GET_WHY_STOPPED:
|
|
||||||
{
|
|
||||||
port_id replyPort
|
|
||||||
= commandMessage.get_why_stopped.reply_port;
|
|
||||||
|
|
||||||
// prepare the message
|
|
||||||
debug_thread_stopped stoppedMessage;
|
|
||||||
prepare_thread_stopped_message(stoppedMessage, whyStopped,
|
|
||||||
nubPort, additionalData);
|
|
||||||
|
|
||||||
// send it
|
|
||||||
error = kill_interruptable_write_port(replyPort, event,
|
|
||||||
&stoppedMessage, sizeof(stoppedMessage));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_DEBUGGED_THREAD_SET_CPU_STATE:
|
case B_DEBUGGED_THREAD_SET_CPU_STATE:
|
||||||
{
|
{
|
||||||
TRACE(("thread_hit_debug_event(): thread: %ld: "
|
TRACE(("thread_hit_debug_event(): thread: %ld: "
|
||||||
@@ -392,6 +359,23 @@ thread_hit_debug_event_internal(uint32 event, const void *message, int32 size,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case B_DEBUGGED_THREAD_GET_CPU_STATE:
|
||||||
|
{
|
||||||
|
port_id replyPort = commandMessage.get_cpu_state.reply_port;
|
||||||
|
|
||||||
|
// prepare the message
|
||||||
|
debug_nub_get_cpu_state_reply replyMessage;
|
||||||
|
replyMessage.error = B_OK;
|
||||||
|
replyMessage.message = event;
|
||||||
|
arch_get_debug_cpu_state(&replyMessage.cpu_state);
|
||||||
|
|
||||||
|
// send it
|
||||||
|
error = kill_interruptable_write_port(replyPort, event,
|
||||||
|
&replyMessage, sizeof(replyMessage));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case B_DEBUGGED_THREAD_DEBUGGER_CHANGED:
|
case B_DEBUGGED_THREAD_DEBUGGER_CHANGED:
|
||||||
{
|
{
|
||||||
// Check, if the debugger really changed, i.e. is different
|
// Check, if the debugger really changed, i.e. is different
|
||||||
@@ -464,15 +448,15 @@ thread_hit_debug_event_internal(uint32 event, const void *message, int32 size,
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
thread_hit_debug_event(uint32 event, const void *message, int32 size,
|
thread_hit_debug_event(debug_debugger_message event, const void *message,
|
||||||
debug_why_stopped whyStopped, void *additionalData, bool requireDebugger)
|
int32 size, bool requireDebugger)
|
||||||
{
|
{
|
||||||
status_t result;
|
status_t result;
|
||||||
bool restart;
|
bool restart;
|
||||||
do {
|
do {
|
||||||
restart = false;
|
restart = false;
|
||||||
result = thread_hit_debug_event_internal(event, message, size,
|
result = thread_hit_debug_event_internal(event, message, size,
|
||||||
whyStopped, additionalData, requireDebugger, restart);
|
requireDebugger, restart);
|
||||||
} while (result >= 0 && restart);
|
} while (result >= 0 && restart);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -509,7 +493,7 @@ user_debug_pre_syscall(uint32 syscall, void *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
thread_hit_debug_event(B_DEBUGGER_MESSAGE_PRE_SYSCALL, &message,
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_PRE_SYSCALL, &message,
|
||||||
sizeof(message), B_PRE_SYSCALL_HIT, NULL, true);
|
sizeof(message), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -547,30 +531,7 @@ user_debug_post_syscall(uint32 syscall, void *args, uint64 returnValue,
|
|||||||
}
|
}
|
||||||
|
|
||||||
thread_hit_debug_event(B_DEBUGGER_MESSAGE_POST_SYSCALL, &message,
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_POST_SYSCALL, &message,
|
||||||
sizeof(message), B_POST_SYSCALL_HIT, NULL, true);
|
sizeof(message), true);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
stop_thread(debug_why_stopped whyStopped, void *additionalData)
|
|
||||||
{
|
|
||||||
// ensure that a debugger is installed for this team
|
|
||||||
port_id nubPort;
|
|
||||||
status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
|
|
||||||
if (error != B_OK) {
|
|
||||||
dprintf("user_debug_stop_thread(): Failed to install debugger: "
|
|
||||||
"thread: %ld: %s\n", thread_get_current_thread()->id,
|
|
||||||
strerror(error));
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare the message
|
|
||||||
debug_thread_stopped message;
|
|
||||||
prepare_thread_stopped_message(message, whyStopped, nubPort,
|
|
||||||
additionalData);
|
|
||||||
|
|
||||||
return thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_STOPPED, &message,
|
|
||||||
sizeof(message), whyStopped, additionalData, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -604,8 +565,7 @@ user_debug_exception_occurred(debug_exception_type exception, int signal)
|
|||||||
message.signal = signal;
|
message.signal = signal;
|
||||||
|
|
||||||
status_t result = thread_hit_debug_event(
|
status_t result = thread_hit_debug_event(
|
||||||
B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED,
|
B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED, &message, sizeof(message), true);
|
||||||
&message, sizeof(message), B_EXCEPTION_OCCURRED, NULL, true);
|
|
||||||
return (result != B_THREAD_DEBUG_IGNORE_EVENT);
|
return (result != B_THREAD_DEBUG_IGNORE_EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,7 +591,7 @@ user_debug_handle_signal(int signal, struct sigaction *handler, bool deadly)
|
|||||||
message.deadly = deadly;
|
message.deadly = deadly;
|
||||||
|
|
||||||
status_t result = thread_hit_debug_event(B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED,
|
status_t result = thread_hit_debug_event(B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED,
|
||||||
&message, sizeof(message), B_SIGNAL_RECEIVED, NULL, true);
|
&message, sizeof(message), true);
|
||||||
return (result != B_THREAD_DEBUG_IGNORE_EVENT);
|
return (result != B_THREAD_DEBUG_IGNORE_EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +599,24 @@ user_debug_handle_signal(int signal, struct sigaction *handler, bool deadly)
|
|||||||
void
|
void
|
||||||
user_debug_stop_thread()
|
user_debug_stop_thread()
|
||||||
{
|
{
|
||||||
stop_thread(B_THREAD_NOT_RUNNING, NULL);
|
// ensure that a debugger is installed for this team
|
||||||
|
struct thread *thread = thread_get_current_thread();
|
||||||
|
port_id nubPort;
|
||||||
|
status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
|
||||||
|
if (error != B_OK) {
|
||||||
|
dprintf("user_debug_stop_thread(): Failed to install debugger: "
|
||||||
|
"thread: %ld: %s\n", thread->id, strerror(error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare the message
|
||||||
|
debug_thread_debugged message;
|
||||||
|
message.origin.thread = thread->id;
|
||||||
|
message.origin.team = thread->team->id;
|
||||||
|
message.origin.nub_port = nubPort;
|
||||||
|
|
||||||
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_DEBUGGED, &message,
|
||||||
|
sizeof(message), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -663,7 +640,7 @@ user_debug_team_created(team_id teamID)
|
|||||||
message.new_team = teamID;
|
message.new_team = teamID;
|
||||||
|
|
||||||
thread_hit_debug_event(B_DEBUGGER_MESSAGE_TEAM_CREATED, &message,
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_TEAM_CREATED, &message,
|
||||||
sizeof(message), B_TEAM_CREATED, NULL, true);
|
sizeof(message), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -701,7 +678,7 @@ user_debug_thread_created(thread_id threadID)
|
|||||||
message.new_thread = threadID;
|
message.new_thread = threadID;
|
||||||
|
|
||||||
thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_CREATED, &message,
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_CREATED, &message,
|
||||||
sizeof(message), B_THREAD_CREATED, NULL, true);
|
sizeof(message), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -766,7 +743,7 @@ user_debug_image_created(const image_info *imageInfo)
|
|||||||
memcpy(&message.info, imageInfo, sizeof(image_info));
|
memcpy(&message.info, imageInfo, sizeof(image_info));
|
||||||
|
|
||||||
thread_hit_debug_event(B_DEBUGGER_MESSAGE_IMAGE_CREATED, &message,
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_IMAGE_CREATED, &message,
|
||||||
sizeof(message), B_IMAGE_CREATED, NULL, true);
|
sizeof(message), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -789,21 +766,83 @@ user_debug_image_deleted(const image_info *imageInfo)
|
|||||||
memcpy(&message.info, imageInfo, sizeof(image_info));
|
memcpy(&message.info, imageInfo, sizeof(image_info));
|
||||||
|
|
||||||
thread_hit_debug_event(B_DEBUGGER_MESSAGE_IMAGE_CREATED, &message,
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_IMAGE_CREATED, &message,
|
||||||
sizeof(message), B_IMAGE_DELETED, NULL, true);
|
sizeof(message), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
user_debug_break_or_watchpoint_hit(bool watchpoint)
|
user_debug_breakpoint_hit(bool software)
|
||||||
{
|
{
|
||||||
stop_thread((watchpoint ? B_WATCHPOINT_HIT : B_BREAKPOINT_HIT), NULL);
|
// ensure that a debugger is installed for this team
|
||||||
|
struct thread *thread = thread_get_current_thread();
|
||||||
|
port_id nubPort;
|
||||||
|
status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
|
||||||
|
if (error != B_OK) {
|
||||||
|
dprintf("user_debug_breakpoint_hit(): Failed to install debugger: "
|
||||||
|
"thread: %ld: %s\n", thread->id, strerror(error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare the message
|
||||||
|
debug_breakpoint_hit message;
|
||||||
|
message.origin.thread = thread->id;
|
||||||
|
message.origin.team = thread->team->id;
|
||||||
|
message.origin.nub_port = nubPort;
|
||||||
|
message.software = software;
|
||||||
|
arch_get_debug_cpu_state(&message.cpu_state);
|
||||||
|
|
||||||
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_BREAKPOINT_HIT, &message,
|
||||||
|
sizeof(message), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
user_debug_watchpoint_hit()
|
||||||
|
{
|
||||||
|
// ensure that a debugger is installed for this team
|
||||||
|
struct thread *thread = thread_get_current_thread();
|
||||||
|
port_id nubPort;
|
||||||
|
status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
|
||||||
|
if (error != B_OK) {
|
||||||
|
dprintf("user_debug_watchpoint_hit(): Failed to install debugger: "
|
||||||
|
"thread: %ld: %s\n", thread->id, strerror(error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare the message
|
||||||
|
debug_watchpoint_hit message;
|
||||||
|
message.origin.thread = thread->id;
|
||||||
|
message.origin.team = thread->team->id;
|
||||||
|
message.origin.nub_port = nubPort;
|
||||||
|
arch_get_debug_cpu_state(&message.cpu_state);
|
||||||
|
|
||||||
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_WATCHPOINT_HIT, &message,
|
||||||
|
sizeof(message), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
user_debug_single_stepped()
|
user_debug_single_stepped()
|
||||||
{
|
{
|
||||||
stop_thread(B_SINGLE_STEP, NULL);
|
// ensure that a debugger is installed for this team
|
||||||
|
struct thread *thread = thread_get_current_thread();
|
||||||
|
port_id nubPort;
|
||||||
|
status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
|
||||||
|
if (error != B_OK) {
|
||||||
|
dprintf("user_debug_watchpoint_hit(): Failed to install debugger: "
|
||||||
|
"thread: %ld: %s\n", thread->id, strerror(error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare the message
|
||||||
|
debug_single_step message;
|
||||||
|
message.origin.thread = thread->id;
|
||||||
|
message.origin.team = thread->team->id;
|
||||||
|
message.origin.nub_port = nubPort;
|
||||||
|
arch_get_debug_cpu_state(&message.cpu_state);
|
||||||
|
|
||||||
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_SINGLE_STEP, &message,
|
||||||
|
sizeof(message), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -935,6 +974,40 @@ read_user_memory(const void *_address, void *_buffer, int32 size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief Debug nub thread helper function that returns the debug port of
|
||||||
|
* a thread of the same team.
|
||||||
|
*/
|
||||||
|
static status_t
|
||||||
|
debug_nub_thread_get_thread_debug_port(struct thread *nubThread,
|
||||||
|
thread_id threadID, port_id &threadDebugPort)
|
||||||
|
{
|
||||||
|
status_t result = B_OK;
|
||||||
|
threadDebugPort = -1;
|
||||||
|
|
||||||
|
cpu_status state = disable_interrupts();
|
||||||
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
|
struct thread *thread = thread_get_thread_struct_locked(threadID);
|
||||||
|
if (thread) {
|
||||||
|
if (thread->team != nubThread->team)
|
||||||
|
result = B_BAD_VALUE;
|
||||||
|
else if (thread->debug_info.flags & B_THREAD_DEBUG_STOPPED)
|
||||||
|
threadDebugPort = thread->debug_info.debug_port;
|
||||||
|
else
|
||||||
|
result = B_BAD_VALUE;
|
||||||
|
} else
|
||||||
|
result = B_BAD_THREAD_ID;
|
||||||
|
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
if (result == B_OK && threadDebugPort < 0)
|
||||||
|
result = B_ERROR;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
debug_nub_thread(void *)
|
debug_nub_thread(void *)
|
||||||
{
|
{
|
||||||
@@ -984,6 +1057,7 @@ debug_nub_thread(void *)
|
|||||||
union {
|
union {
|
||||||
debug_nub_read_memory_reply read_memory;
|
debug_nub_read_memory_reply read_memory;
|
||||||
debug_nub_write_memory_reply write_memory;
|
debug_nub_write_memory_reply write_memory;
|
||||||
|
debug_nub_get_cpu_state_reply get_cpu_state;
|
||||||
debug_nub_set_breakpoint_reply set_breakpoint;
|
debug_nub_set_breakpoint_reply set_breakpoint;
|
||||||
debug_nub_set_watchpoint_reply set_watchpoint;
|
debug_nub_set_watchpoint_reply set_watchpoint;
|
||||||
debug_nub_get_signal_masks_reply get_signal_masks;
|
debug_nub_get_signal_masks_reply get_signal_masks;
|
||||||
@@ -1112,51 +1186,33 @@ debug_nub_thread(void *)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case B_DEBUG_MESSAGE_RUN_THREAD:
|
case B_DEBUG_MESSAGE_CONTINUE_THREAD:
|
||||||
case B_DEBUG_MESSAGE_STEP_THREAD:
|
|
||||||
{
|
{
|
||||||
// get the parameters
|
// get the parameters
|
||||||
thread_id threadID;
|
thread_id threadID;
|
||||||
uint32 handleEvent;
|
uint32 handleEvent;
|
||||||
bool singleStep;
|
bool singleStep;
|
||||||
|
|
||||||
if (command == B_DEBUG_MESSAGE_RUN_THREAD) {
|
threadID = message.continue_thread.thread;
|
||||||
threadID = message.run_thread.thread;
|
handleEvent = message.continue_thread.handle_event;
|
||||||
handleEvent = message.run_thread.handle_event;
|
singleStep = message.continue_thread.single_step;
|
||||||
singleStep = false;
|
|
||||||
} else {
|
|
||||||
threadID = message.step_thread.thread;
|
|
||||||
handleEvent = message.step_thread.handle_event;
|
|
||||||
singleStep = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_%s_THREAD: "
|
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_CONTINUE_THREAD: "
|
||||||
"thread: %ld, handle event: %lu\n", nubThread->id,
|
"thread: %ld, handle event: %lu, single step: %d\n",
|
||||||
(singleStep ? "STEP" : "RUN"), threadID,
|
nubThread->id, threadID, handleEvent, singleStep));
|
||||||
handleEvent));
|
|
||||||
|
|
||||||
// find the thread and get its debug port
|
// find the thread and get its debug port
|
||||||
state = disable_interrupts();
|
|
||||||
GRAB_THREAD_LOCK();
|
|
||||||
|
|
||||||
port_id threadDebugPort = -1;
|
port_id threadDebugPort = -1;
|
||||||
struct thread *thread
|
status_t result = debug_nub_thread_get_thread_debug_port(
|
||||||
= thread_get_thread_struct_locked(threadID);
|
nubThread, threadID, threadDebugPort);
|
||||||
if (thread && thread->team == nubThread->team
|
|
||||||
&& thread->debug_info.flags & B_THREAD_DEBUG_STOPPED) {
|
|
||||||
threadDebugPort = thread->debug_info.debug_port;
|
|
||||||
}
|
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
// send a message to the debugged thread
|
// send a message to the debugged thread
|
||||||
if (threadDebugPort >= 0) {
|
if (result == B_OK) {
|
||||||
debugged_thread_continue commandMessage;
|
debugged_thread_continue commandMessage;
|
||||||
commandMessage.handle_event = handleEvent;
|
commandMessage.handle_event = handleEvent;
|
||||||
commandMessage.single_step = singleStep;
|
commandMessage.single_step = singleStep;
|
||||||
|
|
||||||
write_port(threadDebugPort,
|
result = write_port(threadDebugPort,
|
||||||
B_DEBUGGED_THREAD_MESSAGE_CONTINUE,
|
B_DEBUGGED_THREAD_MESSAGE_CONTINUE,
|
||||||
&commandMessage, sizeof(commandMessage));
|
&commandMessage, sizeof(commandMessage));
|
||||||
}
|
}
|
||||||
@@ -1164,42 +1220,6 @@ debug_nub_thread(void *)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case B_DEBUG_MESSAGE_GET_WHY_STOPPED:
|
|
||||||
{
|
|
||||||
// get the parameters
|
|
||||||
thread_id threadID = message.get_why_stopped.thread;
|
|
||||||
port_id replyPort = message.get_why_stopped.reply_port;
|
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_WHY_STOPPED: "
|
|
||||||
"thread: %ld\n", nubThread->id, threadID));
|
|
||||||
|
|
||||||
// find the thread and get its debug port
|
|
||||||
state = disable_interrupts();
|
|
||||||
GRAB_THREAD_LOCK();
|
|
||||||
|
|
||||||
port_id threadDebugPort = -1;
|
|
||||||
struct thread *thread
|
|
||||||
= thread_get_thread_struct_locked(threadID);
|
|
||||||
if (thread && thread->team == nubThread->team
|
|
||||||
&& thread->debug_info.flags & B_THREAD_DEBUG_STOPPED) {
|
|
||||||
threadDebugPort = thread->debug_info.debug_port;
|
|
||||||
}
|
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
// send a message to the debugged thread
|
|
||||||
if (threadDebugPort >= 0) {
|
|
||||||
debugged_thread_get_why_stopped commandMessage;
|
|
||||||
commandMessage.reply_port = replyPort;
|
|
||||||
write_port(threadDebugPort,
|
|
||||||
B_DEBUGGED_THREAD_GET_WHY_STOPPED, &commandMessage,
|
|
||||||
sizeof(commandMessage));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_DEBUG_MESSAGE_SET_CPU_STATE:
|
case B_DEBUG_MESSAGE_SET_CPU_STATE:
|
||||||
{
|
{
|
||||||
// get the parameters
|
// get the parameters
|
||||||
@@ -1211,22 +1231,12 @@ debug_nub_thread(void *)
|
|||||||
"thread: %ld\n", nubThread->id, threadID));
|
"thread: %ld\n", nubThread->id, threadID));
|
||||||
|
|
||||||
// find the thread and get its debug port
|
// find the thread and get its debug port
|
||||||
state = disable_interrupts();
|
|
||||||
GRAB_THREAD_LOCK();
|
|
||||||
|
|
||||||
port_id threadDebugPort = -1;
|
port_id threadDebugPort = -1;
|
||||||
struct thread *thread
|
status_t result = debug_nub_thread_get_thread_debug_port(
|
||||||
= thread_get_thread_struct_locked(threadID);
|
nubThread, threadID, threadDebugPort);
|
||||||
if (thread && thread->team == nubThread->team
|
|
||||||
&& thread->debug_info.flags & B_THREAD_DEBUG_STOPPED) {
|
|
||||||
threadDebugPort = thread->debug_info.debug_port;
|
|
||||||
}
|
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
// send a message to the debugged thread
|
// send a message to the debugged thread
|
||||||
if (threadDebugPort >= 0) {
|
if (result == B_OK) {
|
||||||
debugged_thread_set_cpu_state commandMessage;
|
debugged_thread_set_cpu_state commandMessage;
|
||||||
memcpy(&commandMessage.cpu_state, &cpuState,
|
memcpy(&commandMessage.cpu_state, &cpuState,
|
||||||
sizeof(debug_cpu_state));
|
sizeof(debug_cpu_state));
|
||||||
@@ -1238,6 +1248,39 @@ debug_nub_thread(void *)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case B_DEBUG_MESSAGE_GET_CPU_STATE:
|
||||||
|
{
|
||||||
|
// get the parameters
|
||||||
|
thread_id threadID = message.get_cpu_state.thread;
|
||||||
|
replyPort = message.get_cpu_state.reply_port;
|
||||||
|
|
||||||
|
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_CPU_STATE: "
|
||||||
|
"thread: %ld\n", nubThread->id, threadID));
|
||||||
|
|
||||||
|
// find the thread and get its debug port
|
||||||
|
port_id threadDebugPort = -1;
|
||||||
|
status_t result = debug_nub_thread_get_thread_debug_port(
|
||||||
|
nubThread, threadID, threadDebugPort);
|
||||||
|
|
||||||
|
// send a message to the debugged thread
|
||||||
|
if (threadDebugPort >= 0) {
|
||||||
|
debugged_thread_get_cpu_state commandMessage;
|
||||||
|
commandMessage.reply_port = replyPort;
|
||||||
|
result = write_port(threadDebugPort,
|
||||||
|
B_DEBUGGED_THREAD_GET_CPU_STATE, &commandMessage,
|
||||||
|
sizeof(commandMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
// send a reply to the debugger in case of error
|
||||||
|
if (result != B_OK) {
|
||||||
|
reply.get_cpu_state.error = result;
|
||||||
|
sendReply = true;
|
||||||
|
replySize = sizeof(reply.get_cpu_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case B_DEBUG_MESSAGE_SET_BREAKPOINT:
|
case B_DEBUG_MESSAGE_SET_BREAKPOINT:
|
||||||
{
|
{
|
||||||
// get the parameters
|
// get the parameters
|
||||||
@@ -1813,19 +1856,35 @@ ensure_debugger_installed(team_id teamID, port_id *_port)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_user_debugger(const char *message)
|
_user_debugger(const char *userMessage)
|
||||||
{
|
{
|
||||||
// install the default debugger, if there is none yet
|
// install the default debugger, if there is none yet
|
||||||
status_t error = ensure_debugger_installed(B_CURRENT_TEAM);
|
struct thread *thread = thread_get_current_thread();
|
||||||
|
port_id nubPort;
|
||||||
|
status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
// time to commit suicide
|
// time to commit suicide
|
||||||
dprintf("_user_debugger(): Failed to install debugger. Message is: "
|
char buffer[128];
|
||||||
"`%s'\n", message);
|
ssize_t length = user_strlcpy(buffer, userMessage, sizeof(buffer));
|
||||||
|
if (length >= 0) {
|
||||||
|
dprintf("_user_debugger(): Failed to install debugger. Message is: "
|
||||||
|
"`%s'\n", buffer);
|
||||||
|
} else {
|
||||||
|
dprintf("_user_debugger(): Failed to install debugger. Message is: "
|
||||||
|
"%p (%s)\n", userMessage, strerror(length));
|
||||||
|
}
|
||||||
_user_exit_team(1);
|
_user_exit_team(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify the debugger
|
// prepare the message
|
||||||
stop_thread(B_DEBUGGER_CALL, (void*)message);
|
debug_debugger_call message;
|
||||||
|
message.origin.thread = thread->id;
|
||||||
|
message.origin.team = thread->team->id;
|
||||||
|
message.origin.nub_port = nubPort;
|
||||||
|
message.message = (void*)userMessage;
|
||||||
|
|
||||||
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_DEBUGGER_CALL, &message,
|
||||||
|
sizeof(message), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1965,7 +2024,6 @@ _user_debug_thread(thread_id threadID)
|
|||||||
void
|
void
|
||||||
_user_wait_for_debugger(void)
|
_user_wait_for_debugger(void)
|
||||||
{
|
{
|
||||||
thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_STOPPED, NULL, 0,
|
thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_DEBUGGED, NULL, 0, false);
|
||||||
B_THREAD_NOT_RUNNING, NULL, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user