Added patch originally written by Ingo Weinhold:
- extended libdebug.so functionality to be able to get stack frames, current instruction pointer, etc. - changed the debug_server to be able to run as a simple BLooper - this saves some trouble when the app_server dies - the debug_server now prints out a stack crawl for the crashed team (without symbols, though - for that data to be helpful you should have a look at the loaded images (ie. where they start)) - the debug_server now also prints the team name when it kills it git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12882 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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 :
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _ARCH_DEBUG_SUPPORT_H
|
||||
#define _ARCH_DEBUG_SUPPORT_H
|
||||
|
||||
#include <debug_support.h>
|
||||
|
||||
#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
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <debug_support.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -3,10 +3,14 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <debug_support.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user