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,
|
ssize_t debug_read_string(debug_context *context, const void *_address,
|
||||||
char *buffer, size_t size);
|
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
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -2,9 +2,14 @@ SubDir OBOS_TOP src kits debug ;
|
|||||||
|
|
||||||
UsePrivateHeaders debug ;
|
UsePrivateHeaders debug ;
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared ;
|
||||||
|
SubDirHdrs [ FDirName $(SUBDIR) arch ] ;
|
||||||
|
|
||||||
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch $(OBOS_ARCH) ] ;
|
||||||
|
|
||||||
SharedLibrary debug :
|
SharedLibrary debug :
|
||||||
debug_support.cpp
|
debug_support.cpp
|
||||||
|
|
||||||
|
arch_debug_support.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
LinkSharedOSLibs libdebug.so :
|
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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <debug_support.h>
|
#include <debug_support.h>
|
||||||
|
|
||||||
|
#include "arch_debug_support.h"
|
||||||
|
|
||||||
|
|
||||||
// init_debug_context
|
// init_debug_context
|
||||||
status_t
|
status_t
|
||||||
init_debug_context(debug_context *context, port_id nubPort)
|
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;
|
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>
|
#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";
|
static const char *kSignature = "application/x-vnd.haiku-debug-server";
|
||||||
|
|
||||||
// message what codes
|
// message what codes
|
||||||
@@ -94,7 +97,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// DebugServer
|
// DebugServer
|
||||||
class DebugServer : public BApplication {
|
class DebugServer
|
||||||
|
#if USE_BE_APPLICATION
|
||||||
|
: public BApplication
|
||||||
|
#else
|
||||||
|
: public BLooper
|
||||||
|
#endif
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
DebugServer(status_t &error);
|
DebugServer(status_t &error);
|
||||||
|
|
||||||
@@ -203,6 +212,39 @@ ThreadDebugHandler::HandleMessage(DebugMessage *message)
|
|||||||
// We just print the error and send a message to ourselves.
|
// We just print the error and send a message to ourselves.
|
||||||
printf("debug_server: Thread %ld entered the debugger: %s\n", fThread,
|
printf("debug_server: Thread %ld entered the debugger: %s\n", fThread,
|
||||||
buffer);
|
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());
|
BMessage alertMessage(*fInvoker->Message());
|
||||||
alertMessage.AddInt32("which", 1);
|
alertMessage.AddInt32("which", 1);
|
||||||
fInvoker->Invoke(&alertMessage);
|
fInvoker->Invoke(&alertMessage);
|
||||||
@@ -369,13 +411,20 @@ TeamDebugHandler::_DeleteThreadHandler(ThreadDebugHandler *handler)
|
|||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
DebugServer::DebugServer(status_t &error)
|
DebugServer::DebugServer(status_t &error)
|
||||||
|
#if USE_BE_APPLICATION
|
||||||
: BApplication(kSignature, &error),
|
: BApplication(kSignature, &error),
|
||||||
|
#else
|
||||||
|
: BLooper(kSignature),
|
||||||
|
#endif
|
||||||
fListenerPort(-1),
|
fListenerPort(-1),
|
||||||
fListener(-1),
|
fListener(-1),
|
||||||
fTerminating(false),
|
fTerminating(false),
|
||||||
fTeamDebugHandlers(),
|
fTeamDebugHandlers(),
|
||||||
fDebugMessages()
|
fDebugMessages()
|
||||||
{
|
{
|
||||||
|
#if !USE_BE_APPLICATION
|
||||||
|
error = B_OK;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
@@ -430,8 +479,13 @@ DebugServer::MessageReceived(BMessage *message)
|
|||||||
|
|
||||||
delete message;
|
delete message;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
|
#if USE_BE_APPLICATION
|
||||||
BApplication::MessageReceived(message);
|
BApplication::MessageReceived(message);
|
||||||
|
#else
|
||||||
|
BLooper::MessageReceived(message);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnterDebugger
|
// EnterDebugger
|
||||||
@@ -446,10 +500,11 @@ DebugServer::EnterDebugger(TeamDebugHandler *handler)
|
|||||||
void
|
void
|
||||||
DebugServer::KillTeam(TeamDebugHandler *handler)
|
DebugServer::KillTeam(TeamDebugHandler *handler)
|
||||||
{
|
{
|
||||||
|
|
||||||
team_id team = handler->Team();
|
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);
|
kill_team(team);
|
||||||
|
|
||||||
@@ -541,7 +596,6 @@ main()
|
|||||||
strerror(error));
|
strerror(error));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// init application
|
// init application
|
||||||
error = server.Init();
|
error = server.Init();
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
@@ -552,5 +606,8 @@ main()
|
|||||||
|
|
||||||
server.Run();
|
server.Run();
|
||||||
|
|
||||||
|
#if !USE_BE_APPLICATION
|
||||||
|
wait_for_thread(server.Thread(), NULL);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user