diff --git a/headers/private/debug/debug_support.h b/headers/private/debug/debug_support.h index 99f7fbbe40..e8ce99876f 100644 --- a/headers/private/debug/debug_support.h +++ b/headers/private/debug/debug_support.h @@ -32,6 +32,23 @@ ssize_t debug_read_memory(debug_context *context, const void *address, ssize_t debug_read_string(debug_context *context, const void *_address, char *buffer, size_t size); +status_t debug_get_cpu_state(debug_context *context, thread_id thread, + debug_debugger_message *messageCode, debug_cpu_state *cpuState); + + +// stack trace support + +typedef struct debug_stack_frame_info { + void *frame; + void *parent_frame; + void *return_address; +} debug_stack_frame_info; + +status_t debug_get_instruction_pointer(debug_context *context, thread_id thread, + void **ip, void **stackFrameAddress); +status_t debug_get_stack_frame(debug_context *context, + void *stackFrameAddress, debug_stack_frame_info *stackFrameInfo); + #ifdef __cplusplus } // extern "C" diff --git a/src/kits/debug/Jamfile b/src/kits/debug/Jamfile index c7774debe7..90321c661c 100644 --- a/src/kits/debug/Jamfile +++ b/src/kits/debug/Jamfile @@ -2,9 +2,14 @@ SubDir OBOS_TOP src kits debug ; UsePrivateHeaders debug ; UsePrivateHeaders shared ; +SubDirHdrs [ FDirName $(SUBDIR) arch ] ; + +SEARCH_SOURCE += [ FDirName $(SUBDIR) arch $(OBOS_ARCH) ] ; SharedLibrary debug : debug_support.cpp + + arch_debug_support.cpp ; LinkSharedOSLibs libdebug.so : diff --git a/src/kits/debug/arch/arch_debug_support.h b/src/kits/debug/arch/arch_debug_support.h new file mode 100644 index 0000000000..7cf056b9e9 --- /dev/null +++ b/src/kits/debug/arch/arch_debug_support.h @@ -0,0 +1,23 @@ +/* + * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ +#ifndef _ARCH_DEBUG_SUPPORT_H +#define _ARCH_DEBUG_SUPPORT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +status_t arch_debug_get_instruction_pointer(debug_context *context, + thread_id thread, void **ip, void **stackFrameAddress); +status_t arch_debug_get_stack_frame(debug_context *context, + void *stackFrameAddress, debug_stack_frame_info *stackFrameInfo); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _ARCH_DEBUG_SUPPORT_H diff --git a/src/kits/debug/arch/x86/arch_debug_support.cpp b/src/kits/debug/arch/x86/arch_debug_support.cpp new file mode 100644 index 0000000000..1968ede786 --- /dev/null +++ b/src/kits/debug/arch/x86/arch_debug_support.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include "arch_debug_support.h" + + +struct stack_frame { + struct stack_frame *previous; + void *return_address; +}; + + +status_t +arch_debug_get_instruction_pointer(debug_context *context, thread_id thread, + void **ip, void **stackFrameAddress) +{ + // get the CPU state + debug_cpu_state cpuState; + status_t error = debug_get_cpu_state(context, thread, NULL, &cpuState); + if (error != B_OK) + return error; + + *ip = (void*)cpuState.eip; + *stackFrameAddress = (void*)cpuState.ebp; + + return B_OK; +} + + +status_t +arch_debug_get_stack_frame(debug_context *context, void *stackFrameAddress, + debug_stack_frame_info *stackFrameInfo) +{ + stack_frame stackFrame; + ssize_t bytesRead = debug_read_memory(context, stackFrameAddress, &stackFrame, + sizeof(stackFrame)); + if (bytesRead < B_OK) + return bytesRead; + if (bytesRead != sizeof(stackFrame)) + return B_ERROR; + + stackFrameInfo->frame = stackFrameAddress; + stackFrameInfo->parent_frame = stackFrame.previous; + stackFrameInfo->return_address = stackFrame.return_address; + return B_OK; +} diff --git a/src/kits/debug/debug_support.cpp b/src/kits/debug/debug_support.cpp index acff29a564..2406f0ff4f 100644 --- a/src/kits/debug/debug_support.cpp +++ b/src/kits/debug/debug_support.cpp @@ -3,10 +3,14 @@ * Distributed under the terms of the MIT License. */ + #include #include +#include "arch_debug_support.h" + + // init_debug_context status_t init_debug_context(debug_context *context, port_id nubPort) @@ -179,3 +183,56 @@ debug_read_string(debug_context *context, const void *_address, char *buffer, return sumRead; } + +status_t +debug_get_cpu_state(debug_context *context, thread_id thread, + debug_debugger_message *messageCode, debug_cpu_state *cpuState) +{ + if (!context || !cpuState) + return B_BAD_VALUE; + + // prepare message + debug_nub_get_cpu_state message; + message.reply_port = context->reply_port; + message.thread = thread; + + // send message + debug_nub_get_cpu_state_reply reply; + status_t error = send_debug_message(context, B_DEBUG_MESSAGE_GET_CPU_STATE, + &message, sizeof(message), &reply, sizeof(reply)); + if (error == B_OK) + error = reply.error; + + // get state + if (error == B_OK) { + *cpuState = reply.cpu_state; + if (messageCode) + *messageCode = reply.message; + } + + return error; +} + + +status_t +debug_get_instruction_pointer(debug_context *context, thread_id thread, + void **ip, void **stackFrameAddress) +{ + if (!context || !ip || !stackFrameAddress) + return B_BAD_VALUE; + + return arch_debug_get_instruction_pointer(context, thread, ip, + stackFrameAddress); +} + + +status_t +debug_get_stack_frame(debug_context *context, void *stackFrameAddress, + debug_stack_frame_info *stackFrameInfo) +{ + if (!context || !stackFrameAddress || !stackFrameInfo) + return B_BAD_VALUE; + + return arch_debug_get_stack_frame(context, stackFrameAddress, + stackFrameInfo); +} diff --git a/src/servers/debug/DebugServer.cpp b/src/servers/debug/DebugServer.cpp index 1a02f09e8d..3fc4904f9e 100644 --- a/src/servers/debug/DebugServer.cpp +++ b/src/servers/debug/DebugServer.cpp @@ -17,6 +17,9 @@ #include +#define USE_BE_APPLICATION 0 + // define this if the debug server should be a standard BApplication + static const char *kSignature = "application/x-vnd.haiku-debug-server"; // message what codes @@ -94,7 +97,13 @@ private: }; // DebugServer -class DebugServer : public BApplication { +class DebugServer +#if USE_BE_APPLICATION + : public BApplication +#else + : public BLooper +#endif +{ public: DebugServer(status_t &error); @@ -203,6 +212,39 @@ ThreadDebugHandler::HandleMessage(DebugMessage *message) // We just print the error and send a message to ourselves. printf("debug_server: Thread %ld entered the debugger: %s\n", fThread, buffer); + +// TODO: Temporary solution. Remove when attaching gdb is working. +#if 1 + // print a stacktrace + void *ip = NULL; + void *stackFrameAddress = NULL; + debug_context context; + status_t error = init_debug_context(&context, + message->Data().origin.nub_port); + + if (error == B_OK) { + error = debug_get_instruction_pointer(&context, + message->Data().origin.thread, &ip, &stackFrameAddress); + } + + if (error == B_OK) { + printf("stack trace, current PC %p:\n", ip); + + for (int32 i = 0; i < 50; i++) { + debug_stack_frame_info stackFrameInfo; + + error = debug_get_stack_frame(&context, stackFrameAddress, + &stackFrameInfo); + if (error < B_OK || stackFrameInfo.parent_frame == NULL) + break; + + printf(" (%p) %p\n", stackFrameInfo.frame, + stackFrameInfo.return_address); + stackFrameAddress = stackFrameInfo.parent_frame; + } + } +#endif + BMessage alertMessage(*fInvoker->Message()); alertMessage.AddInt32("which", 1); fInvoker->Invoke(&alertMessage); @@ -369,13 +411,20 @@ TeamDebugHandler::_DeleteThreadHandler(ThreadDebugHandler *handler) // constructor DebugServer::DebugServer(status_t &error) +#if USE_BE_APPLICATION : BApplication(kSignature, &error), +#else + : BLooper(kSignature), +#endif fListenerPort(-1), fListener(-1), fTerminating(false), fTeamDebugHandlers(), fDebugMessages() { +#if !USE_BE_APPLICATION + error = B_OK; +#endif } // Init @@ -430,8 +479,13 @@ DebugServer::MessageReceived(BMessage *message) delete message; } - } else + } else { +#if USE_BE_APPLICATION BApplication::MessageReceived(message); +#else + BLooper::MessageReceived(message); +#endif + } } // EnterDebugger @@ -446,10 +500,11 @@ DebugServer::EnterDebugger(TeamDebugHandler *handler) void DebugServer::KillTeam(TeamDebugHandler *handler) { - team_id team = handler->Team(); + team_info info; + get_team_info(team, &info); - fprintf(stderr, "debug_server: Killing team %ld\n", team); + fprintf(stderr, "debug_server: Killing team %ld (%s)\n", team, info.args); kill_team(team); @@ -541,7 +596,6 @@ main() strerror(error)); exit(1); } - // init application error = server.Init(); if (error != B_OK) { @@ -552,5 +606,8 @@ main() server.Run(); +#if !USE_BE_APPLICATION + wait_for_thread(server.Thread(), NULL); +#endif return 0; }