* Added new team flag B_TEAM_DEBUG_PREVENT_EXIT that prevents teams from exiting
via exit() (the calling thread will drop into the debugger instead). * The DebugServer now uses this flag by default. * Added TODO comment: the default debugger should already be able to set a flag like this in order to close a race condition between dropping a thread into the debugger and setting the flag. * Cleaned up the debug_server sources a bit. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36265 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
#ifndef _DEBUGGER_H
|
#ifndef _DEBUGGER_H
|
||||||
#define _DEBUGGER_H
|
#define _DEBUGGER_H
|
||||||
|
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include <image.h>
|
#include <image.h>
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
#include <arch/mipsel/arch_debugger.h>
|
#include <arch/mipsel/arch_debugger.h>
|
||||||
#include <arch/arm/arch_debugger.h>
|
#include <arch/arm/arch_debugger.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef __INTEL__
|
#ifdef __INTEL__
|
||||||
typedef struct x86_debug_cpu_state debug_cpu_state;
|
typedef struct x86_debug_cpu_state debug_cpu_state;
|
||||||
#elif __POWERPC__
|
#elif __POWERPC__
|
||||||
@@ -64,6 +66,7 @@ enum {
|
|||||||
B_TEAM_DEBUG_TEAM_CREATION = 0x00080000,
|
B_TEAM_DEBUG_TEAM_CREATION = 0x00080000,
|
||||||
B_TEAM_DEBUG_THREADS = 0x00100000,
|
B_TEAM_DEBUG_THREADS = 0x00100000,
|
||||||
B_TEAM_DEBUG_IMAGES = 0x00200000,
|
B_TEAM_DEBUG_IMAGES = 0x00200000,
|
||||||
|
B_TEAM_DEBUG_PREVENT_EXIT = 0x00400000,
|
||||||
|
|
||||||
// new thread handling
|
// new thread handling
|
||||||
B_TEAM_DEBUG_STOP_NEW_THREADS = 0x01000000,
|
B_TEAM_DEBUG_STOP_NEW_THREADS = 0x01000000,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
|
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
#define USE_GUI true
|
#define USE_GUI true
|
||||||
// define to false if the debug server shouldn't use GUI (i.e. an alert)
|
// define to false if the debug server shouldn't use GUI (i.e. an alert)
|
||||||
|
|
||||||
@@ -35,9 +37,11 @@
|
|||||||
# define TRACE(x) ;
|
# define TRACE(x) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
using std::map;
|
using std::map;
|
||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
|
|
||||||
|
|
||||||
static const char *kSignature = "application/x-vnd.Haiku-debug_server";
|
static const char *kSignature = "application/x-vnd.Haiku-debug_server";
|
||||||
|
|
||||||
// paths to the apps used for debugging
|
// paths to the apps used for debugging
|
||||||
@@ -46,7 +50,6 @@ static const char *kTerminalPath = "/boot/system/apps/Terminal";
|
|||||||
static const char *kGDBPath = "/bin/gdb";
|
static const char *kGDBPath = "/bin/gdb";
|
||||||
|
|
||||||
|
|
||||||
// KillTeam
|
|
||||||
static void
|
static void
|
||||||
KillTeam(team_id team, const char *appName = NULL)
|
KillTeam(team_id team, const char *appName = NULL)
|
||||||
{
|
{
|
||||||
@@ -71,7 +74,7 @@ KillTeam(team_id team, const char *appName = NULL)
|
|||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// DebugMessage
|
|
||||||
class DebugMessage : public DoublyLinkedListLinkImpl<DebugMessage> {
|
class DebugMessage : public DoublyLinkedListLinkImpl<DebugMessage> {
|
||||||
public:
|
public:
|
||||||
DebugMessage()
|
DebugMessage()
|
||||||
@@ -92,7 +95,6 @@ private:
|
|||||||
typedef DoublyLinkedList<DebugMessage> DebugMessageList;
|
typedef DoublyLinkedList<DebugMessage> DebugMessageList;
|
||||||
|
|
||||||
|
|
||||||
// TeamDebugHandler
|
|
||||||
class TeamDebugHandler : public BLocker {
|
class TeamDebugHandler : public BLocker {
|
||||||
public:
|
public:
|
||||||
TeamDebugHandler(team_id team);
|
TeamDebugHandler(team_id team);
|
||||||
@@ -144,11 +146,11 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// TeamDebugHandlerRoster
|
|
||||||
class TeamDebugHandlerRoster : public BLocker {
|
class TeamDebugHandlerRoster : public BLocker {
|
||||||
private:
|
private:
|
||||||
TeamDebugHandlerRoster()
|
TeamDebugHandlerRoster()
|
||||||
: BLocker("team debug handler roster")
|
:
|
||||||
|
BLocker("team debug handler roster")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +261,6 @@ private:
|
|||||||
TeamDebugHandlerRoster *TeamDebugHandlerRoster::sRoster = NULL;
|
TeamDebugHandlerRoster *TeamDebugHandlerRoster::sRoster = NULL;
|
||||||
|
|
||||||
|
|
||||||
// DebugServer
|
|
||||||
class DebugServer : public BServer {
|
class DebugServer : public BServer {
|
||||||
public:
|
public:
|
||||||
DebugServer(status_t &error);
|
DebugServer(status_t &error);
|
||||||
@@ -285,13 +286,14 @@ private:
|
|||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// constructor
|
|
||||||
TeamDebugHandler::TeamDebugHandler(team_id team)
|
TeamDebugHandler::TeamDebugHandler(team_id team)
|
||||||
: BLocker("team debug handler"),
|
:
|
||||||
fMessages(),
|
BLocker("team debug handler"),
|
||||||
fMessageCountSem(-1),
|
fMessages(),
|
||||||
fTeam(team),
|
fMessageCountSem(-1),
|
||||||
fHandlerThread(-1)
|
fTeam(team),
|
||||||
|
fHandlerThread(-1)
|
||||||
{
|
{
|
||||||
fDebugContext.nub_port = -1;
|
fDebugContext.nub_port = -1;
|
||||||
fDebugContext.reply_port = -1;
|
fDebugContext.reply_port = -1;
|
||||||
@@ -299,7 +301,7 @@ TeamDebugHandler::TeamDebugHandler(team_id team)
|
|||||||
fExecutablePath[0] = '\0';
|
fExecutablePath[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
|
||||||
TeamDebugHandler::~TeamDebugHandler()
|
TeamDebugHandler::~TeamDebugHandler()
|
||||||
{
|
{
|
||||||
// delete the message count semaphore and wait for the thread to die
|
// delete the message count semaphore and wait for the thread to die
|
||||||
@@ -322,7 +324,7 @@ TeamDebugHandler::~TeamDebugHandler()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init
|
|
||||||
status_t
|
status_t
|
||||||
TeamDebugHandler::Init(port_id nubPort)
|
TeamDebugHandler::Init(port_id nubPort)
|
||||||
{
|
{
|
||||||
@@ -352,6 +354,13 @@ TeamDebugHandler::Init(port_id nubPort)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set team flags
|
||||||
|
debug_nub_set_team_flags message;
|
||||||
|
message.flags = B_TEAM_DEBUG_PREVENT_EXIT;
|
||||||
|
|
||||||
|
send_debug_message(&fDebugContext, B_DEBUG_MESSAGE_SET_TEAM_FLAGS, &message,
|
||||||
|
sizeof(message), NULL, 0);
|
||||||
|
|
||||||
// create the message count semaphore
|
// create the message count semaphore
|
||||||
char name[B_OS_NAME_LENGTH];
|
char name[B_OS_NAME_LENGTH];
|
||||||
snprintf(name, sizeof(name), "team %ld message count", fTeam);
|
snprintf(name, sizeof(name), "team %ld message count", fTeam);
|
||||||
@@ -377,14 +386,14 @@ TeamDebugHandler::Init(port_id nubPort)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Team
|
|
||||||
team_id
|
team_id
|
||||||
TeamDebugHandler::Team() const
|
TeamDebugHandler::Team() const
|
||||||
{
|
{
|
||||||
return fTeam;
|
return fTeam;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PushMessage
|
|
||||||
status_t
|
status_t
|
||||||
TeamDebugHandler::PushMessage(DebugMessage *message)
|
TeamDebugHandler::PushMessage(DebugMessage *message)
|
||||||
{
|
{
|
||||||
@@ -396,7 +405,7 @@ TeamDebugHandler::PushMessage(DebugMessage *message)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _PopMessage
|
|
||||||
status_t
|
status_t
|
||||||
TeamDebugHandler::_PopMessage(DebugMessage *&message)
|
TeamDebugHandler::_PopMessage(DebugMessage *&message)
|
||||||
{
|
{
|
||||||
@@ -418,7 +427,7 @@ TeamDebugHandler::_PopMessage(DebugMessage *&message)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _EnterDebugger
|
|
||||||
thread_id
|
thread_id
|
||||||
TeamDebugHandler::_EnterDebugger()
|
TeamDebugHandler::_EnterDebugger()
|
||||||
{
|
{
|
||||||
@@ -482,14 +491,14 @@ TeamDebugHandler::_EnterDebugger()
|
|||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _KillTeam
|
|
||||||
void
|
void
|
||||||
TeamDebugHandler::_KillTeam()
|
TeamDebugHandler::_KillTeam()
|
||||||
{
|
{
|
||||||
KillTeam(fTeam, fTeamInfo.args);
|
KillTeam(fTeam, fTeamInfo.args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// _HandleMessage
|
|
||||||
bool
|
bool
|
||||||
TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
||||||
{
|
{
|
||||||
@@ -577,7 +586,7 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
|||||||
return kill;
|
return kill;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _LookupSymbolAddress
|
|
||||||
void
|
void
|
||||||
TeamDebugHandler::_LookupSymbolAddress(
|
TeamDebugHandler::_LookupSymbolAddress(
|
||||||
debug_symbol_lookup_context *lookupContext, const void *address,
|
debug_symbol_lookup_context *lookupContext, const void *address,
|
||||||
@@ -631,7 +640,7 @@ TeamDebugHandler::_LookupSymbolAddress(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// _PrintStackTrace
|
|
||||||
void
|
void
|
||||||
TeamDebugHandler::_PrintStackTrace(thread_id thread)
|
TeamDebugHandler::_PrintStackTrace(thread_id thread)
|
||||||
{
|
{
|
||||||
@@ -707,7 +716,6 @@ TeamDebugHandler::_NotifyRegistrar(team_id team, bool openAlert,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// _InitGUI
|
|
||||||
status_t
|
status_t
|
||||||
TeamDebugHandler::_InitGUI()
|
TeamDebugHandler::_InitGUI()
|
||||||
{
|
{
|
||||||
@@ -716,14 +724,14 @@ TeamDebugHandler::_InitGUI()
|
|||||||
return app->InitGUIContext();
|
return app->InitGUIContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
// _HandlerThreadEntry
|
|
||||||
status_t
|
status_t
|
||||||
TeamDebugHandler::_HandlerThreadEntry(void *data)
|
TeamDebugHandler::_HandlerThreadEntry(void *data)
|
||||||
{
|
{
|
||||||
return ((TeamDebugHandler*)data)->_HandlerThread();
|
return ((TeamDebugHandler*)data)->_HandlerThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
// _HandlerThread
|
|
||||||
status_t
|
status_t
|
||||||
TeamDebugHandler::_HandlerThread()
|
TeamDebugHandler::_HandlerThread()
|
||||||
{
|
{
|
||||||
@@ -806,35 +814,35 @@ TeamDebugHandler::_HandlerThread()
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _ExecutableNameEquals
|
|
||||||
bool
|
bool
|
||||||
TeamDebugHandler::_ExecutableNameEquals(const char *name) const
|
TeamDebugHandler::_ExecutableNameEquals(const char *name) const
|
||||||
{
|
{
|
||||||
return strcmp(_LastPathComponent(fExecutablePath), name) == 0;
|
return strcmp(_LastPathComponent(fExecutablePath), name) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _IsAppServer
|
|
||||||
bool
|
bool
|
||||||
TeamDebugHandler::_IsAppServer() const
|
TeamDebugHandler::_IsAppServer() const
|
||||||
{
|
{
|
||||||
return _ExecutableNameEquals("app_server");
|
return _ExecutableNameEquals("app_server");
|
||||||
}
|
}
|
||||||
|
|
||||||
// _IsInputServer
|
|
||||||
bool
|
bool
|
||||||
TeamDebugHandler::_IsInputServer() const
|
TeamDebugHandler::_IsInputServer() const
|
||||||
{
|
{
|
||||||
return _ExecutableNameEquals("input_server");
|
return _ExecutableNameEquals("input_server");
|
||||||
}
|
}
|
||||||
|
|
||||||
// _IsRegistrar
|
|
||||||
bool
|
bool
|
||||||
TeamDebugHandler::_IsRegistrar() const
|
TeamDebugHandler::_IsRegistrar() const
|
||||||
{
|
{
|
||||||
return _ExecutableNameEquals("registrar");
|
return _ExecutableNameEquals("registrar");
|
||||||
}
|
}
|
||||||
|
|
||||||
// _IsGUIServer
|
|
||||||
bool
|
bool
|
||||||
TeamDebugHandler::_IsGUIServer() const
|
TeamDebugHandler::_IsGUIServer() const
|
||||||
{
|
{
|
||||||
@@ -842,7 +850,7 @@ TeamDebugHandler::_IsGUIServer() const
|
|||||||
return _IsAppServer() || _IsInputServer() || _IsRegistrar();
|
return _IsAppServer() || _IsInputServer() || _IsRegistrar();
|
||||||
}
|
}
|
||||||
|
|
||||||
// _LastPathComponent
|
|
||||||
const char *
|
const char *
|
||||||
TeamDebugHandler::_LastPathComponent(const char *path)
|
TeamDebugHandler::_LastPathComponent(const char *path)
|
||||||
{
|
{
|
||||||
@@ -850,7 +858,7 @@ TeamDebugHandler::_LastPathComponent(const char *path)
|
|||||||
return lastSlash ? lastSlash + 1 : path;
|
return lastSlash ? lastSlash + 1 : path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _FindTeam
|
|
||||||
team_id
|
team_id
|
||||||
TeamDebugHandler::_FindTeam(const char *name)
|
TeamDebugHandler::_FindTeam(const char *name)
|
||||||
{
|
{
|
||||||
@@ -868,7 +876,7 @@ TeamDebugHandler::_FindTeam(const char *name)
|
|||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _AreGUIServersAlive
|
|
||||||
bool
|
bool
|
||||||
TeamDebugHandler::_AreGUIServersAlive()
|
TeamDebugHandler::_AreGUIServersAlive()
|
||||||
{
|
{
|
||||||
@@ -879,16 +887,17 @@ TeamDebugHandler::_AreGUIServersAlive()
|
|||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// constructor
|
|
||||||
DebugServer::DebugServer(status_t &error)
|
DebugServer::DebugServer(status_t &error)
|
||||||
: BServer(kSignature, false, &error),
|
:
|
||||||
fListenerPort(-1),
|
BServer(kSignature, false, &error),
|
||||||
fListener(-1),
|
fListenerPort(-1),
|
||||||
fTerminating(false)
|
fListener(-1),
|
||||||
|
fTerminating(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init
|
|
||||||
status_t
|
status_t
|
||||||
DebugServer::Init()
|
DebugServer::Init()
|
||||||
{
|
{
|
||||||
@@ -904,6 +913,7 @@ DebugServer::Init()
|
|||||||
return fListener;
|
return fListener;
|
||||||
|
|
||||||
// register as default debugger
|
// register as default debugger
|
||||||
|
// TODO: could set default flags
|
||||||
status_t error = install_default_debugger(fListenerPort);
|
status_t error = install_default_debugger(fListenerPort);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
@@ -922,14 +932,14 @@ DebugServer::QuitRequested()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _ListenerEntry
|
|
||||||
status_t
|
status_t
|
||||||
DebugServer::_ListenerEntry(void *data)
|
DebugServer::_ListenerEntry(void *data)
|
||||||
{
|
{
|
||||||
return ((DebugServer*)data)->_Listener();
|
return ((DebugServer*)data)->_Listener();
|
||||||
}
|
}
|
||||||
|
|
||||||
// _Listener
|
|
||||||
status_t
|
status_t
|
||||||
DebugServer::_Listener()
|
DebugServer::_Listener()
|
||||||
{
|
{
|
||||||
@@ -963,7 +973,7 @@ message->Data().origin.team, code));
|
|||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// main
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3496,7 +3496,8 @@ void
|
|||||||
_user_exit_team(status_t returnValue)
|
_user_exit_team(status_t returnValue)
|
||||||
{
|
{
|
||||||
struct thread* thread = thread_get_current_thread();
|
struct thread* thread = thread_get_current_thread();
|
||||||
struct thread* mainThread = thread->team->main_thread;
|
struct team* team = thread->team;
|
||||||
|
struct thread* mainThread = team->main_thread;
|
||||||
|
|
||||||
mainThread->exit.status = returnValue;
|
mainThread->exit.status = returnValue;
|
||||||
mainThread->exit.reason = THREAD_RETURN_EXIT;
|
mainThread->exit.reason = THREAD_RETURN_EXIT;
|
||||||
@@ -3507,6 +3508,13 @@ _user_exit_team(status_t returnValue)
|
|||||||
thread->exit.reason = THREAD_RETURN_EXIT;
|
thread->exit.reason = THREAD_RETURN_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((atomic_get(&team->debug_info.flags) & B_TEAM_DEBUG_PREVENT_EXIT)
|
||||||
|
!= 0) {
|
||||||
|
// This team is currently being debugged, and requested that teams
|
||||||
|
// should not be exited.
|
||||||
|
user_debug_stop_thread();
|
||||||
|
}
|
||||||
|
|
||||||
send_signal(thread->id, SIGKILL);
|
send_signal(thread->id, SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user