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:
Axel Dörfler
2005-05-29 00:44:51 +00:00
parent 697bc06297
commit b2c1ecd640
6 changed files with 215 additions and 5 deletions
+17
View File
@@ -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"
+5
View File
@@ -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 :
+23
View File
@@ -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;
}
+57
View File
@@ -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);
}
+62 -5
View File
@@ -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;
}