mirror of
https://github.com/id-Software/DOOM-3.git
synced 2026-03-20 00:49:31 +01:00
hello world
This commit is contained in:
166
neo/tools/debugger/DebuggerApp.cpp
Normal file
166
neo/tools/debugger/DebuggerApp.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../../sys/win32/rc/debugger_resource.h"
|
||||
#include "DebuggerApp.h"
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerApp::rvDebuggerApp
|
||||
================
|
||||
*/
|
||||
rvDebuggerApp::rvDebuggerApp ( ) :
|
||||
mOptions ( "Software\\id Software\\DOOM3\\Tools\\Debugger" )
|
||||
{
|
||||
mInstance = NULL;
|
||||
mDebuggerWindow = NULL;
|
||||
mAccelerators = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerApp::~rvDebuggerApp
|
||||
================
|
||||
*/
|
||||
rvDebuggerApp::~rvDebuggerApp ( )
|
||||
{
|
||||
if ( mAccelerators )
|
||||
{
|
||||
DestroyAcceleratorTable ( mAccelerators );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerApp::Initialize
|
||||
|
||||
Initializes the debugger application by creating the debugger window
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerApp::Initialize ( HINSTANCE instance )
|
||||
{
|
||||
INITCOMMONCONTROLSEX ex;
|
||||
ex.dwICC = ICC_USEREX_CLASSES | ICC_LISTVIEW_CLASSES | ICC_WIN95_CLASSES;
|
||||
ex.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
||||
|
||||
mInstance = instance;
|
||||
|
||||
mOptions.Load ( );
|
||||
|
||||
mDebuggerWindow = new rvDebuggerWindow;
|
||||
|
||||
if ( !mDebuggerWindow->Create ( instance ) )
|
||||
{
|
||||
delete mDebuggerWindow;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the network connection for the debugger
|
||||
if ( !mClient.Initialize ( ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mAccelerators = LoadAccelerators ( mInstance, MAKEINTRESOURCE(IDR_DBG_ACCELERATORS) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerApp::ProcessWindowMessages
|
||||
|
||||
Process windows messages
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerApp::ProcessWindowMessages ( void )
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
while ( PeekMessage ( &msg, NULL, 0, 0, PM_NOREMOVE ) )
|
||||
{
|
||||
if ( !GetMessage (&msg, NULL, 0, 0) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !TranslateAccelerator ( &msg ) )
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerApp::TranslateAccelerator
|
||||
|
||||
Translate any accelerators destined for this window
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerApp::TranslateAccelerator ( LPMSG msg )
|
||||
{
|
||||
if ( mDebuggerWindow && ::TranslateAccelerator ( mDebuggerWindow->GetWindow(), mAccelerators, msg ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerApp::Run
|
||||
|
||||
Main Loop for the debugger application
|
||||
================
|
||||
*/
|
||||
int rvDebuggerApp::Run ( void )
|
||||
{
|
||||
// Main message loop:
|
||||
while ( ProcessWindowMessages ( ) )
|
||||
{
|
||||
mClient.ProcessMessages ( );
|
||||
|
||||
Sleep ( 0 );
|
||||
}
|
||||
|
||||
mClient.Shutdown ( );
|
||||
mOptions.Save ( );
|
||||
|
||||
delete mDebuggerWindow;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
108
neo/tools/debugger/DebuggerApp.h
Normal file
108
neo/tools/debugger/DebuggerApp.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef DEBUGGERAPP_H_
|
||||
#define DEBUGGERAPP_H_
|
||||
|
||||
#include "../../sys/win32/win_local.h"
|
||||
#include "../../framework/sync/Msg.h"
|
||||
|
||||
#ifndef REGISTRYOPTIONS_H_
|
||||
#include "../common/RegistryOptions.h"
|
||||
#endif
|
||||
|
||||
#ifndef DEBUGGERWINDOW_H_
|
||||
#include "DebuggerWindow.h"
|
||||
#endif
|
||||
|
||||
#ifndef DEBUGGERMESSAGES_H_
|
||||
#include "DebuggerMessages.h"
|
||||
#endif
|
||||
|
||||
#ifndef DEBUGGERCLIENT_H_
|
||||
#include "DebuggerClient.h"
|
||||
#endif
|
||||
|
||||
// These were changed to static by ID so to make it easy we just throw them
|
||||
// in this header
|
||||
const int MAX_MSGLEN = 1400;
|
||||
|
||||
class rvDebuggerApp
|
||||
{
|
||||
public:
|
||||
|
||||
rvDebuggerApp ( );
|
||||
|
||||
bool Initialize ( HINSTANCE hInstance );
|
||||
int Run ( void );
|
||||
|
||||
rvRegistryOptions& GetOptions ( void );
|
||||
rvDebuggerClient& GetClient ( void );
|
||||
rvDebuggerWindow& GetWindow ( void );
|
||||
|
||||
HINSTANCE GetInstance ( void );
|
||||
|
||||
bool TranslateAccelerator ( LPMSG msg );
|
||||
|
||||
protected:
|
||||
|
||||
rvRegistryOptions mOptions;
|
||||
rvDebuggerWindow* mDebuggerWindow;
|
||||
HINSTANCE mInstance;
|
||||
rvDebuggerClient mClient;
|
||||
HACCEL mAccelerators;
|
||||
|
||||
private:
|
||||
|
||||
bool ProcessNetMessages ( void );
|
||||
bool ProcessWindowMessages ( void );
|
||||
};
|
||||
|
||||
ID_INLINE HINSTANCE rvDebuggerApp::GetInstance ( void )
|
||||
{
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
ID_INLINE rvDebuggerClient& rvDebuggerApp::GetClient ( void )
|
||||
{
|
||||
return mClient;
|
||||
}
|
||||
|
||||
ID_INLINE rvRegistryOptions& rvDebuggerApp::GetOptions ( void )
|
||||
{
|
||||
return mOptions;
|
||||
}
|
||||
|
||||
ID_INLINE rvDebuggerWindow& rvDebuggerApp::GetWindow ( void )
|
||||
{
|
||||
assert ( mDebuggerWindow );
|
||||
return *mDebuggerWindow;
|
||||
}
|
||||
|
||||
extern rvDebuggerApp gDebuggerApp;
|
||||
|
||||
#endif // DEBUGGERAPP_H_
|
||||
62
neo/tools/debugger/DebuggerBreakpoint.cpp
Normal file
62
neo/tools/debugger/DebuggerBreakpoint.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "DebuggerApp.h"
|
||||
#include "DebuggerBreakpoint.h"
|
||||
|
||||
int rvDebuggerBreakpoint::mNextID = 1;
|
||||
|
||||
rvDebuggerBreakpoint::rvDebuggerBreakpoint ( const char* filename, int linenumber, int id )
|
||||
{
|
||||
mFilename = filename;
|
||||
mLineNumber = linenumber;
|
||||
mEnabled = true;
|
||||
|
||||
if ( id == -1 )
|
||||
{
|
||||
mID = mNextID++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mID = id;
|
||||
}
|
||||
}
|
||||
|
||||
rvDebuggerBreakpoint::rvDebuggerBreakpoint ( rvDebuggerBreakpoint& bp )
|
||||
{
|
||||
mFilename = bp.mFilename;
|
||||
mEnabled = bp.mEnabled;
|
||||
mLineNumber = bp.mLineNumber;
|
||||
}
|
||||
|
||||
rvDebuggerBreakpoint::~rvDebuggerBreakpoint ( void )
|
||||
{
|
||||
}
|
||||
70
neo/tools/debugger/DebuggerBreakpoint.h
Normal file
70
neo/tools/debugger/DebuggerBreakpoint.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef DEBUGGERBREAKPOINT_H_
|
||||
#define DEBUGGERBREAKPOINT_H_
|
||||
|
||||
class rvDebuggerBreakpoint
|
||||
{
|
||||
public:
|
||||
|
||||
rvDebuggerBreakpoint ( const char* filename, int linenumber, int id = -1 );
|
||||
rvDebuggerBreakpoint ( rvDebuggerBreakpoint& bp );
|
||||
~rvDebuggerBreakpoint ( void );
|
||||
|
||||
const char* GetFilename ( void );
|
||||
int GetLineNumber ( void );
|
||||
int GetID ( void );
|
||||
|
||||
protected:
|
||||
|
||||
bool mEnabled;
|
||||
int mID;
|
||||
int mLineNumber;
|
||||
idStr mFilename;
|
||||
|
||||
private:
|
||||
|
||||
static int mNextID;
|
||||
};
|
||||
|
||||
ID_INLINE const char* rvDebuggerBreakpoint::GetFilename ( void )
|
||||
{
|
||||
return mFilename;
|
||||
}
|
||||
|
||||
ID_INLINE int rvDebuggerBreakpoint::GetLineNumber ( void )
|
||||
{
|
||||
return mLineNumber;
|
||||
}
|
||||
|
||||
ID_INLINE int rvDebuggerBreakpoint::GetID ( void )
|
||||
{
|
||||
return mID;
|
||||
}
|
||||
|
||||
#endif // DEBUGGERBREAKPOINT_H_
|
||||
586
neo/tools/debugger/DebuggerClient.cpp
Normal file
586
neo/tools/debugger/DebuggerClient.cpp
Normal file
@@ -0,0 +1,586 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "DebuggerApp.h"
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::rvDebuggerClient
|
||||
================
|
||||
*/
|
||||
rvDebuggerClient::rvDebuggerClient ( )
|
||||
{
|
||||
mConnected = false;
|
||||
mWaitFor = DBMSG_UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::~rvDebuggerClient
|
||||
================
|
||||
*/
|
||||
rvDebuggerClient::~rvDebuggerClient ( )
|
||||
{
|
||||
ClearBreakpoints ( );
|
||||
ClearCallstack ( );
|
||||
ClearThreads ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::Initialize
|
||||
|
||||
Initialize the debugger client
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerClient::Initialize ( void )
|
||||
{
|
||||
// Nothing else can run with the debugger
|
||||
com_editors = EDITOR_DEBUGGER;
|
||||
|
||||
// Initialize the network connection
|
||||
if ( !mPort.InitForPort ( 27981 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Server must be running on the local host on port 28980
|
||||
Sys_StringToNetAdr ( "localhost", &mServerAdrt, true );
|
||||
mServerAdr.port = 27980;
|
||||
|
||||
// Attempt to let the server know we are here. The server may not be running so this
|
||||
// message will just get ignored.
|
||||
SendMessage ( DBMSG_CONNECT );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::Shutdown
|
||||
|
||||
Shutdown the debugger client and let the debugger server
|
||||
know we are shutting down
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::Shutdown ( void )
|
||||
{
|
||||
if ( mConnected )
|
||||
{
|
||||
SendMessage ( DBMSG_DISCONNECT );
|
||||
mConnected = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::ProcessMessages
|
||||
|
||||
Process all incomding messages from the debugger server
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerClient::ProcessMessages ( void )
|
||||
{
|
||||
netadr_t adrFrom;
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
|
||||
// Check for pending udp packets on the debugger port
|
||||
while ( mPort.GetPacket ( adrFrom, msg.data, msg.cursize, msg.maxsize ) )
|
||||
{
|
||||
unsigned short command;
|
||||
|
||||
// Only accept packets from the debugger server for security reasons
|
||||
if ( !Sys_CompareNetAdrBase ( adrFrom, mServerAdr ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
command = (unsigned short) MSG_ReadShort ( &msg );
|
||||
|
||||
// Is this what we are waiting for?
|
||||
if ( command == mWaitFor )
|
||||
{
|
||||
mWaitFor = DBMSG_UNKNOWN;
|
||||
}
|
||||
|
||||
switch ( command )
|
||||
{
|
||||
case DBMSG_CONNECT:
|
||||
mConnected = true;
|
||||
SendMessage ( DBMSG_CONNECTED );
|
||||
SendBreakpoints ( );
|
||||
break;
|
||||
|
||||
case DBMSG_CONNECTED:
|
||||
mConnected = true;
|
||||
SendBreakpoints ( );
|
||||
break;
|
||||
|
||||
case DBMSG_DISCONNECT:
|
||||
mConnected = false;
|
||||
break;
|
||||
|
||||
case DBMSG_BREAK:
|
||||
HandleBreak ( &msg );
|
||||
break;
|
||||
|
||||
// Callstack being send to the client
|
||||
case DBMSG_INSPECTCALLSTACK:
|
||||
HandleInspectCallstack ( &msg );
|
||||
break;
|
||||
|
||||
// Thread list is being sent to the client
|
||||
case DBMSG_INSPECTTHREADS:
|
||||
HandleInspectThreads ( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_INSPECTVARIABLE:
|
||||
HandleInspectVariable ( &msg );
|
||||
break;
|
||||
}
|
||||
|
||||
// Give the window a chance to process the message
|
||||
msg.readcount = 0;
|
||||
msg.bit = 0;
|
||||
gDebuggerApp.GetWindow().ProcessNetMessage ( &msg );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::HandleBreak
|
||||
|
||||
Handle the DBMSG_BREAK message send from the server. This message is handled
|
||||
by caching the file and linenumber where the break occured.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::HandleBreak ( msg_t* msg )
|
||||
{
|
||||
char filename[MAX_PATH];
|
||||
|
||||
mBreak = true;
|
||||
|
||||
// Line number
|
||||
mBreakLineNumber = MSG_ReadLong ( msg );
|
||||
|
||||
// Filename
|
||||
MSG_ReadString ( msg, filename, MAX_PATH );
|
||||
mBreakFilename = filename;
|
||||
|
||||
// Clear the variables
|
||||
mVariables.Clear ( );
|
||||
|
||||
// Request the callstack and threads
|
||||
SendMessage ( DBMSG_INSPECTCALLSTACK );
|
||||
WaitFor ( DBMSG_INSPECTCALLSTACK, 2000 );
|
||||
|
||||
SendMessage ( DBMSG_INSPECTTHREADS );
|
||||
WaitFor ( DBMSG_INSPECTTHREADS, 2000 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::InspectVariable
|
||||
|
||||
Instructs the client to inspect the given variable at the given callstack depth. The
|
||||
variable is inspected by sending a DBMSG_INSPECTVARIABLE message to the server which
|
||||
will in turn respond back to the client with the variable value
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::InspectVariable ( const char* name, int callstackDepth )
|
||||
{
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTVARIABLE );
|
||||
MSG_WriteShort ( &msg, (short)(mCallstack.Num()-callstackDepth) );
|
||||
MSG_WriteString ( &msg, name );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::HandleInspectCallstack
|
||||
|
||||
Handle the message DBMSG_INSPECTCALLSTACK being sent from the server. This message
|
||||
is handled by adding the callstack entries to a list for later lookup.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::HandleInspectCallstack ( msg_t* msg )
|
||||
{
|
||||
int depth;
|
||||
|
||||
ClearCallstack ( );
|
||||
|
||||
// Read all of the callstack entries specfied in the message
|
||||
for ( depth = (short)MSG_ReadShort ( msg ) ; depth > 0; depth -- )
|
||||
{
|
||||
rvDebuggerCallstack* entry = new rvDebuggerCallstack;
|
||||
|
||||
char temp[1024];
|
||||
|
||||
// Function name
|
||||
MSG_ReadString ( msg, temp, 1024 );
|
||||
entry->mFunction = temp;
|
||||
|
||||
// Filename
|
||||
MSG_ReadString ( msg, temp, 1024 );
|
||||
entry->mFilename = temp;
|
||||
|
||||
// Line Number
|
||||
entry->mLineNumber = MSG_ReadLong ( msg );
|
||||
|
||||
// Add to list
|
||||
mCallstack.Append ( entry );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::HandleInspectThreads
|
||||
|
||||
Handle the message DBMSG_INSPECTTHREADS being sent from the server. This message
|
||||
is handled by adding the list of threads to a list for later lookup.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::HandleInspectThreads ( msg_t* msg )
|
||||
{
|
||||
int count;
|
||||
|
||||
ClearThreads ( );
|
||||
|
||||
// Loop over the number of threads in the message
|
||||
for ( count = (short)MSG_ReadShort ( msg ) ; count > 0; count -- )
|
||||
{
|
||||
rvDebuggerThread* entry = new rvDebuggerThread;
|
||||
|
||||
char temp[1024];
|
||||
|
||||
// Thread name
|
||||
MSG_ReadString ( msg, temp, 1024 );
|
||||
entry->mName = temp;
|
||||
|
||||
// Thread ID
|
||||
entry->mID = MSG_ReadLong ( msg );
|
||||
|
||||
// Thread state
|
||||
entry->mCurrent = MSG_ReadBits ( msg, 1 ) ? true : false;
|
||||
entry->mDoneProcessing = MSG_ReadBits ( msg, 1 ) ? true : false;
|
||||
entry->mWaiting = MSG_ReadBits ( msg, 1 ) ? true : false;
|
||||
entry->mDying = MSG_ReadBits ( msg, 1 ) ? true : false;
|
||||
|
||||
// Add thread to list
|
||||
mThreads.Append ( entry );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::HandleInspectVariable
|
||||
|
||||
Handle the message DBMSG_INSPECTVARIABLE being sent from the server. This message
|
||||
is handled by adding the inspected variable to a dictionary for later lookup
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::HandleInspectVariable ( msg_t* msg )
|
||||
{
|
||||
char var[1024];
|
||||
char value[1024];
|
||||
int callDepth;
|
||||
|
||||
callDepth = (short)MSG_ReadShort ( msg );
|
||||
MSG_ReadString ( msg, var, 1024 );
|
||||
MSG_ReadString ( msg, value, 1024 );
|
||||
|
||||
mVariables.Set ( va("%d:%s", mCallstack.Num()-callDepth, var), value );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::WaitFor
|
||||
|
||||
Waits the given amount of time for the specified message to be received by the
|
||||
debugger client.
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerClient::WaitFor ( EDebuggerMessage msg, int time )
|
||||
{
|
||||
int start;
|
||||
|
||||
// Cant wait if not connected
|
||||
if ( !mConnected )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
start = Sys_Milliseconds ( );
|
||||
mWaitFor = msg;
|
||||
|
||||
while ( mWaitFor != DBMSG_UNKNOWN && Sys_Milliseconds()-start < time )
|
||||
{
|
||||
ProcessMessages ( );
|
||||
Sleep ( 0 );
|
||||
}
|
||||
|
||||
if ( mWaitFor != DBMSG_UNKNOWN )
|
||||
{
|
||||
mWaitFor = DBMSG_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::FindBreakpoint
|
||||
|
||||
Searches for a breakpoint that maches the given filename and linenumber
|
||||
================
|
||||
*/
|
||||
rvDebuggerBreakpoint* rvDebuggerClient::FindBreakpoint ( const char* filename, int linenumber )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < mBreakpoints.Num(); i ++ )
|
||||
{
|
||||
rvDebuggerBreakpoint* bp = mBreakpoints[i];
|
||||
|
||||
if ( linenumber == bp->GetLineNumber ( ) && !idStr::Icmp ( bp->GetFilename ( ), filename ) )
|
||||
{
|
||||
return bp;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::ClearBreakpoints
|
||||
|
||||
Removes all breakpoints from the client and server
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::ClearBreakpoints ( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < GetBreakpointCount(); i ++ )
|
||||
{
|
||||
rvDebuggerBreakpoint* bp = mBreakpoints[i];
|
||||
assert ( bp );
|
||||
|
||||
SendRemoveBreakpoint ( *bp );
|
||||
delete bp;
|
||||
}
|
||||
|
||||
mBreakpoints.Clear ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::AddBreakpoint
|
||||
|
||||
Adds a breakpoint to the client and server with the give nfilename and linenumber
|
||||
================
|
||||
*/
|
||||
int rvDebuggerClient::AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly )
|
||||
{
|
||||
int index = mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber ) );
|
||||
|
||||
SendAddBreakpoint ( *mBreakpoints[index] );
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::RemoveBreakpoint
|
||||
|
||||
Removes the breakpoint with the given ID from the client and server
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerClient::RemoveBreakpoint ( int bpID )
|
||||
{
|
||||
int index;
|
||||
|
||||
for ( index = 0; index < GetBreakpointCount(); index ++ )
|
||||
{
|
||||
if ( mBreakpoints[index]->GetID ( ) == bpID )
|
||||
{
|
||||
SendRemoveBreakpoint ( *mBreakpoints[index] );
|
||||
delete mBreakpoints[index];
|
||||
mBreakpoints.RemoveIndex ( index );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::SendMessage
|
||||
|
||||
Send a message with no data to the debugger server
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::SendMessage ( EDebuggerMessage dbmsg )
|
||||
{
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)dbmsg );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::SendBreakpoints
|
||||
|
||||
Send all breakpoints to the debugger server
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::SendBreakpoints ( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( !mConnected )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Send all the breakpoints to the server
|
||||
for ( i = 0; i < mBreakpoints.Num(); i ++ )
|
||||
{
|
||||
SendAddBreakpoint ( *mBreakpoints[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::SendAddBreakpoint
|
||||
|
||||
Send an individual breakpoint over to the debugger server
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOnly )
|
||||
{
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
if ( !mConnected )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_ADDBREAKPOINT );
|
||||
MSG_WriteBits ( &msg, onceOnly?1:0, 1 );
|
||||
MSG_WriteLong ( &msg, (unsigned long) bp.GetLineNumber ( ) );
|
||||
MSG_WriteLong ( &msg, bp.GetID ( ) );
|
||||
MSG_WriteString ( &msg, bp.GetFilename() );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::SendRemoveBreakpoint
|
||||
|
||||
Sends a remove breakpoint message to the debugger server
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::SendRemoveBreakpoint ( rvDebuggerBreakpoint& bp )
|
||||
{
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
if ( !mConnected )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_REMOVEBREAKPOINT );
|
||||
MSG_WriteLong ( &msg, bp.GetID() );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::ClearCallstack
|
||||
|
||||
Clear all callstack entries
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::ClearCallstack ( void )
|
||||
{
|
||||
int depth;
|
||||
|
||||
for ( depth = 0; depth < mCallstack.Num(); depth ++ )
|
||||
{
|
||||
delete mCallstack[depth];
|
||||
}
|
||||
|
||||
mCallstack.Clear ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::ClearThreads
|
||||
|
||||
Clear all thread entries
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::ClearThreads ( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < mThreads.Num(); i ++ )
|
||||
{
|
||||
delete mThreads[i];
|
||||
}
|
||||
|
||||
mThreads.Clear ( );
|
||||
}
|
||||
|
||||
289
neo/tools/debugger/DebuggerClient.h
Normal file
289
neo/tools/debugger/DebuggerClient.h
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef DEBUGGERCLIENT_H_
|
||||
#define DEBUGGERCLIENT_H_
|
||||
|
||||
class rvDebuggerCallstack
|
||||
{
|
||||
public:
|
||||
|
||||
idStr mFilename;
|
||||
int mLineNumber;
|
||||
idStr mFunction;
|
||||
};
|
||||
|
||||
class rvDebuggerThread
|
||||
{
|
||||
public:
|
||||
|
||||
idStr mName;
|
||||
int mID;
|
||||
bool mCurrent;
|
||||
bool mDying;
|
||||
bool mWaiting;
|
||||
bool mDoneProcessing;
|
||||
};
|
||||
|
||||
#ifndef DEBUGGERBREAKPOINT_H_
|
||||
#include "DebuggerBreakpoint.h"
|
||||
#endif
|
||||
|
||||
typedef idList<rvDebuggerCallstack*> rvDebuggerCallstackList;
|
||||
typedef idList<rvDebuggerThread*> rvDebuggerThreadList;
|
||||
typedef idList<rvDebuggerBreakpoint*> rvDebuggerBreakpointList;
|
||||
|
||||
class rvDebuggerClient
|
||||
{
|
||||
public:
|
||||
|
||||
rvDebuggerClient ( );
|
||||
~rvDebuggerClient ( );
|
||||
|
||||
bool Initialize ( void );
|
||||
void Shutdown ( void );
|
||||
bool ProcessMessages ( void );
|
||||
bool WaitFor ( EDebuggerMessage msg, int time );
|
||||
|
||||
bool IsConnected ( void );
|
||||
bool IsStopped ( void );
|
||||
|
||||
int GetActiveBreakpointID ( void );
|
||||
const char* GetBreakFilename ( void );
|
||||
int GetBreakLineNumber ( void );
|
||||
rvDebuggerCallstackList& GetCallstack ( void );
|
||||
rvDebuggerThreadList& GetThreads ( void );
|
||||
const char* GetVariableValue ( const char* name, int stackDepth );
|
||||
|
||||
void InspectVariable ( const char* name, int callstackDepth );
|
||||
|
||||
void Break ( void );
|
||||
void Resume ( void );
|
||||
void StepInto ( void );
|
||||
void StepOver ( void );
|
||||
|
||||
// Breakpoints
|
||||
int AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly = false );
|
||||
bool RemoveBreakpoint ( int bpID );
|
||||
void ClearBreakpoints ( void );
|
||||
int GetBreakpointCount ( void );
|
||||
rvDebuggerBreakpoint* GetBreakpoint ( int index );
|
||||
rvDebuggerBreakpoint* FindBreakpoint ( const char* filename, int linenumber );
|
||||
|
||||
protected:
|
||||
|
||||
void SendMessage ( EDebuggerMessage dbmsg );
|
||||
void SendBreakpoints ( void );
|
||||
void SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOnly = false );
|
||||
void SendRemoveBreakpoint ( rvDebuggerBreakpoint& bp );
|
||||
void SendPacket ( void* data, int datasize );
|
||||
|
||||
bool mConnected;
|
||||
netadr_t mServerAdr;
|
||||
idPort mPort;
|
||||
|
||||
bool mBreak;
|
||||
int mBreakID;
|
||||
int mBreakLineNumber;
|
||||
idStr mBreakFilename;
|
||||
|
||||
idDict mVariables;
|
||||
|
||||
rvDebuggerCallstackList mCallstack;
|
||||
rvDebuggerThreadList mThreads;
|
||||
rvDebuggerBreakpointList mBreakpoints;
|
||||
|
||||
EDebuggerMessage mWaitFor;
|
||||
|
||||
private:
|
||||
|
||||
void ClearCallstack ( void );
|
||||
void ClearThreads ( void );
|
||||
|
||||
void UpdateWatches ( void );
|
||||
|
||||
// Network message handlers
|
||||
void HandleBreak ( msg_t* msg );
|
||||
void HandleInspectCallstack ( msg_t* msg );
|
||||
void HandleInspectThreads ( msg_t* msg );
|
||||
void HandleInspectVariable ( msg_t* msg );
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::IsConnected
|
||||
================
|
||||
*/
|
||||
ID_INLINE bool rvDebuggerClient::IsConnected ( void )
|
||||
{
|
||||
return mConnected;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::IsStopped
|
||||
================
|
||||
*/
|
||||
ID_INLINE bool rvDebuggerClient::IsStopped ( void )
|
||||
{
|
||||
return mBreak;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetActiveBreakpointID
|
||||
================
|
||||
*/
|
||||
ID_INLINE int rvDebuggerClient::GetActiveBreakpointID ( void )
|
||||
{
|
||||
return mBreakID;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetBreakFilename
|
||||
================
|
||||
*/
|
||||
ID_INLINE const char* rvDebuggerClient::GetBreakFilename ( void )
|
||||
{
|
||||
return mBreakFilename;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetBreakLineNumber
|
||||
================
|
||||
*/
|
||||
ID_INLINE int rvDebuggerClient::GetBreakLineNumber ( void )
|
||||
{
|
||||
return mBreakLineNumber;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetCallstack
|
||||
================
|
||||
*/
|
||||
ID_INLINE rvDebuggerCallstackList& rvDebuggerClient::GetCallstack ( void )
|
||||
{
|
||||
return mCallstack;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetThreads
|
||||
================
|
||||
*/
|
||||
ID_INLINE rvDebuggerThreadList& rvDebuggerClient::GetThreads ( void )
|
||||
{
|
||||
return mThreads;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetVariableValue
|
||||
================
|
||||
*/
|
||||
ID_INLINE const char* rvDebuggerClient::GetVariableValue ( const char* var, int stackDepth )
|
||||
{
|
||||
return mVariables.GetString ( va("%d:%s",stackDepth,var), "" );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetBreakpointCount
|
||||
================
|
||||
*/
|
||||
ID_INLINE int rvDebuggerClient::GetBreakpointCount ( void )
|
||||
{
|
||||
return mBreakpoints.Num ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetBreakpoint
|
||||
================
|
||||
*/
|
||||
ID_INLINE rvDebuggerBreakpoint* rvDebuggerClient::GetBreakpoint ( int index )
|
||||
{
|
||||
return mBreakpoints[index];
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::Break
|
||||
================
|
||||
*/
|
||||
ID_INLINE void rvDebuggerClient::Break ( void )
|
||||
{
|
||||
SendMessage ( DBMSG_BREAK );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::Resume
|
||||
================
|
||||
*/
|
||||
ID_INLINE void rvDebuggerClient::Resume ( void )
|
||||
{
|
||||
mBreak = false;
|
||||
SendMessage ( DBMSG_RESUME );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::StepOver
|
||||
================
|
||||
*/
|
||||
ID_INLINE void rvDebuggerClient::StepOver ( void )
|
||||
{
|
||||
mBreak = false;
|
||||
SendMessage ( DBMSG_STEPOVER );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::StepInto
|
||||
================
|
||||
*/
|
||||
ID_INLINE void rvDebuggerClient::StepInto ( void )
|
||||
{
|
||||
mBreak = false;
|
||||
SendMessage ( DBMSG_STEPINTO );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::SendPacket
|
||||
================
|
||||
*/
|
||||
ID_INLINE void rvDebuggerClient::SendPacket ( void* data, int size )
|
||||
{
|
||||
mPort.SendPacket ( mServerAdr, data, size );
|
||||
}
|
||||
|
||||
#endif // DEBUGGERCLIENT_H_
|
||||
106
neo/tools/debugger/DebuggerFindDlg.cpp
Normal file
106
neo/tools/debugger/DebuggerFindDlg.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../../sys/win32/rc/debugger_resource.h"
|
||||
#include "DebuggerApp.h"
|
||||
#include "DebuggerFindDlg.h"
|
||||
|
||||
char rvDebuggerFindDlg::mFindText[ 256 ];
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerFindDlg::rvDebuggerFindDlg
|
||||
================
|
||||
*/
|
||||
rvDebuggerFindDlg::rvDebuggerFindDlg ( void )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerFindDlg::DoModal
|
||||
|
||||
Launch the dialog
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerFindDlg::DoModal ( rvDebuggerWindow* parent )
|
||||
{
|
||||
if ( DialogBoxParam ( parent->GetInstance(), MAKEINTRESOURCE(IDD_DBG_FIND), parent->GetWindow(), DlgProc, (LONG)this ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvrvDebuggerFindDlg::DlgProc
|
||||
|
||||
Dialog Procedure for the find dialog
|
||||
================
|
||||
*/
|
||||
INT_PTR CALLBACK rvDebuggerFindDlg::DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
||||
{
|
||||
rvDebuggerFindDlg* dlg = (rvDebuggerFindDlg*) GetWindowLong ( wnd, GWL_USERDATA );
|
||||
|
||||
switch ( msg )
|
||||
{
|
||||
case WM_CLOSE:
|
||||
EndDialog ( wnd, 0 );
|
||||
break;
|
||||
|
||||
case WM_INITDIALOG:
|
||||
dlg = (rvDebuggerFindDlg*) lparam;
|
||||
SetWindowLong ( wnd, GWL_USERDATA, (LONG) dlg );
|
||||
dlg->mWnd = wnd;
|
||||
SetWindowText ( GetDlgItem ( dlg->mWnd, IDC_DBG_FIND ), dlg->mFindText );
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch ( LOWORD(wparam) )
|
||||
{
|
||||
case IDOK:
|
||||
{
|
||||
GetWindowText ( GetDlgItem ( wnd, IDC_DBG_FIND ), dlg->mFindText, sizeof( dlg->mFindText ) - 1 );
|
||||
EndDialog ( wnd, 1 );
|
||||
break;
|
||||
}
|
||||
|
||||
case IDCANCEL:
|
||||
EndDialog ( wnd, 0 );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
59
neo/tools/debugger/DebuggerFindDlg.h
Normal file
59
neo/tools/debugger/DebuggerFindDlg.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef DEBUGGERFINDDLG_H_
|
||||
#define DEBUGGERFINDDLG_H_
|
||||
|
||||
class rvDebuggerWindow;
|
||||
|
||||
class rvDebuggerFindDlg
|
||||
{
|
||||
public:
|
||||
|
||||
rvDebuggerFindDlg ( );
|
||||
|
||||
bool DoModal ( rvDebuggerWindow* window );
|
||||
|
||||
const char* GetFindText ( void );
|
||||
|
||||
protected:
|
||||
|
||||
HWND mWnd;
|
||||
|
||||
private:
|
||||
|
||||
static char mFindText[ 256 ];
|
||||
|
||||
static INT_PTR CALLBACK DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
};
|
||||
|
||||
ID_INLINE const char* rvDebuggerFindDlg::GetFindText ( void )
|
||||
{
|
||||
return mFindText;
|
||||
}
|
||||
|
||||
#endif // DEBUGGERFINDDLG_H_
|
||||
51
neo/tools/debugger/DebuggerMessages.h
Normal file
51
neo/tools/debugger/DebuggerMessages.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef DEBUGGERMESSAGES_H_
|
||||
#define DEBUGGERMESSAGES_H_
|
||||
|
||||
enum EDebuggerMessage
|
||||
{
|
||||
DBMSG_UNKNOWN,
|
||||
DBMSG_CONNECT,
|
||||
DBMSG_CONNECTED,
|
||||
DBMSG_DISCONNECT,
|
||||
DBMSG_ADDBREAKPOINT,
|
||||
DBMSG_REMOVEBREAKPOINT,
|
||||
DBMSG_HITBREAKPOINT,
|
||||
DBMSG_RESUME,
|
||||
DBMSG_RESUMED,
|
||||
DBMSG_BREAK,
|
||||
DBMSG_PRINT,
|
||||
DBMSG_INSPECTVARIABLE,
|
||||
DBMSG_INSPECTCALLSTACK,
|
||||
DBMSG_INSPECTTHREADS,
|
||||
DBMSG_STEPOVER,
|
||||
DBMSG_STEPINTO,
|
||||
};
|
||||
|
||||
#endif // DEBUGGER_MESSAGES_H_
|
||||
267
neo/tools/debugger/DebuggerQuickWatchDlg.cpp
Normal file
267
neo/tools/debugger/DebuggerQuickWatchDlg.cpp
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../../sys/win32/rc/debugger_resource.h"
|
||||
#include "DebuggerApp.h"
|
||||
#include "DebuggerQuickWatchDlg.h"
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerQuickWatchDlg::rvDebuggerQuickWatchDlg
|
||||
================
|
||||
*/
|
||||
rvDebuggerQuickWatchDlg::rvDebuggerQuickWatchDlg ( void )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerQuickWatchDlg::DoModal
|
||||
|
||||
Launch the dialog
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerQuickWatchDlg::DoModal ( rvDebuggerWindow* window, int callstackDepth, const char* variable )
|
||||
{
|
||||
mCallstackDepth = callstackDepth;
|
||||
mDebuggerWindow = window;
|
||||
mVariable = variable?variable:"";
|
||||
|
||||
DialogBoxParam ( window->GetInstance(), MAKEINTRESOURCE(IDD_DBG_QUICKWATCH), window->GetWindow(), DlgProc, (LONG)this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerQuickWatchDlg::DlgProc
|
||||
|
||||
Dialog Procedure for the quick watch dialog
|
||||
================
|
||||
*/
|
||||
INT_PTR CALLBACK rvDebuggerQuickWatchDlg::DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
||||
{
|
||||
rvDebuggerQuickWatchDlg* dlg = (rvDebuggerQuickWatchDlg*) GetWindowLong ( wnd, GWL_USERDATA );
|
||||
|
||||
switch ( msg )
|
||||
{
|
||||
case WM_GETMINMAXINFO:
|
||||
{
|
||||
MINMAXINFO* mmi = (MINMAXINFO*)lparam;
|
||||
mmi->ptMinTrackSize.x = 300;
|
||||
mmi->ptMinTrackSize.y = 200;
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CLOSE:
|
||||
gDebuggerApp.GetOptions().SetWindowPlacement ( "wp_quickwatch", wnd );
|
||||
gDebuggerApp.GetOptions().SetColumnWidths ( "cw_quickwatch", GetDlgItem ( wnd, IDC_DBG_CURVALUE ) );
|
||||
EndDialog ( wnd, 0 );
|
||||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
{
|
||||
RECT client;
|
||||
RECT button;
|
||||
|
||||
GetClientRect ( wnd, &client );
|
||||
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_RECALC ), &button );
|
||||
ScreenToClient ( wnd, (POINT*)&button );
|
||||
ScreenToClient ( wnd, (POINT*)&button.right );
|
||||
MoveWindow ( GetDlgItem ( wnd, IDC_DBG_RECALC ), client.right - dlg->mButtonFromRight, button.top, button.right-button.left,button.bottom-button.top, TRUE );
|
||||
|
||||
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_CLOSE ), &button );
|
||||
ScreenToClient ( wnd, (POINT*)&button );
|
||||
ScreenToClient ( wnd, (POINT*)&button.right );
|
||||
MoveWindow ( GetDlgItem ( wnd, IDC_DBG_CLOSE ), client.right - dlg->mButtonFromRight, button.top, button.right-button.left,button.bottom-button.top, TRUE );
|
||||
|
||||
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_ADDWATCH ), &button );
|
||||
ScreenToClient ( wnd, (POINT*)&button );
|
||||
ScreenToClient ( wnd, (POINT*)&button.right );
|
||||
MoveWindow ( GetDlgItem ( wnd, IDC_DBG_ADDWATCH ), client.right - dlg->mButtonFromRight, button.top, button.right-button.left,button.bottom-button.top, TRUE );
|
||||
|
||||
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_VARIABLE ), &button );
|
||||
ScreenToClient ( wnd, (POINT*)&button );
|
||||
ScreenToClient ( wnd, (POINT*)&button.right );
|
||||
MoveWindow ( GetDlgItem ( wnd, IDC_DBG_VARIABLE ), button.left, button.top, client.right-button.left-dlg->mEditFromRight, button.bottom-button.top, TRUE );
|
||||
|
||||
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), &button );
|
||||
ScreenToClient ( wnd, (POINT*)&button );
|
||||
ScreenToClient ( wnd, (POINT*)&button.right );
|
||||
MoveWindow ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), button.left, button.top, client.right-button.left-dlg->mEditFromRight, client.bottom-button.top - dlg->mEditFromBottom, TRUE );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
RECT client;
|
||||
RECT button;
|
||||
|
||||
// Attach the dialog class pointer to the window
|
||||
dlg = (rvDebuggerQuickWatchDlg*) lparam;
|
||||
SetWindowLong ( wnd, GWL_USERDATA, lparam );
|
||||
dlg->mWnd = wnd;
|
||||
|
||||
GetClientRect ( wnd, &client );
|
||||
|
||||
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_RECALC ), &button );
|
||||
ScreenToClient ( wnd, (POINT*)&button );
|
||||
dlg->mButtonFromRight = client.right - button.left;
|
||||
|
||||
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), &button );
|
||||
ScreenToClient ( wnd, (POINT*)&button.right );
|
||||
dlg->mEditFromRight = client.right - button.right;
|
||||
dlg->mEditFromBottom = client.bottom - button.bottom;
|
||||
|
||||
// Disable the value controls until a variable is entered
|
||||
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_ADDWATCH ), false );
|
||||
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_RECALC ), false );
|
||||
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), false );
|
||||
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_CURVALUE_STATIC ), false );
|
||||
|
||||
// Add the columns to the list control
|
||||
LVCOLUMN col;
|
||||
col.mask = LVCF_WIDTH|LVCF_TEXT;
|
||||
col.cx = 100;
|
||||
col.pszText = "Name";
|
||||
ListView_InsertColumn ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), 0, &col );
|
||||
col.cx = 150;
|
||||
col.pszText = "Value";
|
||||
ListView_InsertColumn ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), 1, &col );
|
||||
|
||||
// Set the initial variable if one was given
|
||||
if ( dlg->mVariable.Length() )
|
||||
{
|
||||
dlg->SetVariable ( dlg->mVariable, true );
|
||||
SetWindowText( GetDlgItem ( wnd, IDC_DBG_VARIABLE ), dlg->mVariable );
|
||||
}
|
||||
|
||||
gDebuggerApp.GetOptions().GetWindowPlacement ( "wp_quickwatch", wnd );
|
||||
gDebuggerApp.GetOptions().GetColumnWidths ( "cw_quickwatch", GetDlgItem ( wnd, IDC_DBG_CURVALUE ) );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case WM_COMMAND:
|
||||
switch ( LOWORD(wparam) )
|
||||
{
|
||||
case IDC_DBG_CLOSE:
|
||||
SendMessage ( wnd, WM_CLOSE, 0, 0 );
|
||||
break;
|
||||
|
||||
case IDC_DBG_VARIABLE:
|
||||
// When the variable text changes to something other than empty
|
||||
// we can enable the addwatch and recalc buttons
|
||||
if ( HIWORD(wparam) == EN_CHANGE )
|
||||
{
|
||||
bool enable = GetWindowTextLength ( GetDlgItem ( wnd, IDC_DBG_VARIABLE ) )?true:false;
|
||||
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_ADDWATCH ), enable );
|
||||
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_RECALC ), enable );
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_DBG_ADDWATCH:
|
||||
{
|
||||
char varname[1024];
|
||||
GetWindowText ( GetDlgItem ( wnd, IDC_DBG_VARIABLE ), varname, 1023 );
|
||||
dlg->mDebuggerWindow->AddWatch ( varname );
|
||||
break;
|
||||
}
|
||||
|
||||
case IDC_DBG_RECALC:
|
||||
{
|
||||
char varname[1024];
|
||||
GetWindowText ( GetDlgItem ( wnd, IDC_DBG_VARIABLE ), varname, 1023 );
|
||||
dlg->SetVariable ( varname );
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerQuickWatchDlg::SetVariable
|
||||
|
||||
Sets the current variable being inspected
|
||||
================
|
||||
*/
|
||||
void rvDebuggerQuickWatchDlg::SetVariable ( const char* varname, bool force )
|
||||
{
|
||||
// See if the variable has changed
|
||||
if ( !force && !mVariable.Icmp ( varname ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Throw up a wait cursor
|
||||
SetCursor ( LoadCursor ( NULL, IDC_WAIT ) );
|
||||
|
||||
// Clear the current value list control
|
||||
ListView_DeleteAllItems ( GetDlgItem ( mWnd, IDC_DBG_CURVALUE ) );
|
||||
|
||||
// Get the value of the new variable
|
||||
gDebuggerApp.GetClient().InspectVariable ( varname, mCallstackDepth );
|
||||
|
||||
// Wait for the variable value to be sent over from the debugger server
|
||||
if ( !gDebuggerApp.GetClient().WaitFor ( DBMSG_INSPECTVARIABLE, 2500 ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we got the value of the variable
|
||||
if ( !gDebuggerApp.GetClient().GetVariableValue(varname, mCallstackDepth)[0] )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable the windows that display the current value
|
||||
mVariable = varname;
|
||||
EnableWindow ( GetDlgItem ( mWnd, IDC_DBG_CURVALUE ), true );
|
||||
EnableWindow ( GetDlgItem ( mWnd, IDC_DBG_CURVALUE_STATIC ), true );
|
||||
|
||||
// Add the variablae value to the list control
|
||||
LVITEM item;
|
||||
item.mask = LVIF_TEXT;
|
||||
item.pszText = (LPSTR)varname;
|
||||
item.iItem = 0;
|
||||
item.iSubItem = 0;
|
||||
ListView_InsertItem ( GetDlgItem ( mWnd, IDC_DBG_CURVALUE ), &item );
|
||||
ListView_SetItemText ( GetDlgItem ( mWnd, IDC_DBG_CURVALUE ), 0, 1, (LPSTR)gDebuggerApp.GetClient().GetVariableValue(varname,mCallstackDepth) );
|
||||
|
||||
// Give focus back to the variable edit control and set the cursor back to an arrow
|
||||
SetFocus ( GetDlgItem ( mWnd, IDC_DBG_VARIABLE ) );
|
||||
SetCursor ( LoadCursor ( NULL, IDC_ARROW ) );
|
||||
}
|
||||
59
neo/tools/debugger/DebuggerQuickWatchDlg.h
Normal file
59
neo/tools/debugger/DebuggerQuickWatchDlg.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef DEBUGGERQUICKWATCHDLG_H_
|
||||
#define DEBUGGERQUICKWATCHDLG_H_
|
||||
|
||||
class rvDebuggerWindow;
|
||||
|
||||
class rvDebuggerQuickWatchDlg
|
||||
{
|
||||
public:
|
||||
|
||||
rvDebuggerQuickWatchDlg ( );
|
||||
|
||||
bool DoModal ( rvDebuggerWindow* window, int callstackDepth, const char* variable = NULL );
|
||||
|
||||
protected:
|
||||
|
||||
HWND mWnd;
|
||||
int mCallstackDepth;
|
||||
idStr mVariable;
|
||||
rvDebuggerWindow* mDebuggerWindow;
|
||||
|
||||
void SetVariable ( const char* varname, bool force = false );
|
||||
|
||||
private:
|
||||
|
||||
int mEditFromRight;
|
||||
int mButtonFromRight;
|
||||
int mEditFromBottom;
|
||||
|
||||
static INT_PTR CALLBACK DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
};
|
||||
|
||||
#endif // DEBUGGERQUICKWATCHDLG_H_
|
||||
244
neo/tools/debugger/DebuggerScript.cpp
Normal file
244
neo/tools/debugger/DebuggerScript.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "DebuggerApp.h"
|
||||
#include "DebuggerScript.h"
|
||||
#include "../../game/script/Script_Program.h"
|
||||
#include "../../ui/Window.h"
|
||||
#include "../../ui/UserInterfaceLocal.h"
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerScript::rvDebuggerScript
|
||||
================
|
||||
*/
|
||||
rvDebuggerScript::rvDebuggerScript ( void )
|
||||
{
|
||||
mContents = NULL;
|
||||
mProgram = NULL;
|
||||
mInterface = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerScript::~rvDebuggerScript
|
||||
================
|
||||
*/
|
||||
rvDebuggerScript::~rvDebuggerScript ( void )
|
||||
{
|
||||
Unload ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerScript::Unload
|
||||
|
||||
Unload the script from memory
|
||||
================
|
||||
*/
|
||||
void rvDebuggerScript::Unload ( void )
|
||||
{
|
||||
delete[] mContents;
|
||||
|
||||
if ( mInterface )
|
||||
{
|
||||
delete mInterface;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete mProgram;
|
||||
}
|
||||
|
||||
mContents = NULL;
|
||||
mProgram = NULL;
|
||||
mInterface = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerScript::Load
|
||||
|
||||
Loads the debugger script and attempts to compile it using the method
|
||||
appropriate for the file being loaded. If the script cant be compiled
|
||||
the loading of the script fails
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerScript::Load ( const char* filename )
|
||||
{
|
||||
void* buffer;
|
||||
int size;
|
||||
|
||||
// Unload the script before reloading it
|
||||
Unload ( );
|
||||
|
||||
// Cache the filename used to load the script
|
||||
mFilename = filename;
|
||||
|
||||
// Read in the file
|
||||
size = fileSystem->ReadFile ( filename, &buffer, &mModifiedTime );
|
||||
if ( buffer == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the buffer over
|
||||
mContents = new char [ size + 1 ];
|
||||
memcpy ( mContents, buffer, size );
|
||||
mContents[size] = 0;
|
||||
|
||||
// Cleanup
|
||||
fileSystem->FreeFile ( buffer );
|
||||
|
||||
// Now compile the script so we can tell what a valid line is, etc.. If its
|
||||
// a gui file then we need to parse it using the userinterface system rather
|
||||
// than the normal script compiler.
|
||||
try
|
||||
{
|
||||
// Parse the script using the script compiler
|
||||
mProgram = new idProgram;
|
||||
mProgram->BeginCompilation ( );
|
||||
mProgram->CompileFile ( SCRIPT_DEFAULT );
|
||||
|
||||
//BSM Nerve: Loads a game specific main script file
|
||||
idStr gamedir = cvarSystem->GetCVarString( "fs_game" );
|
||||
if(gamedir.Length() > 0) {
|
||||
|
||||
idStr scriptFile = va("script/%s_main.script", gamedir.c_str());
|
||||
if(fileSystem->ReadFile(scriptFile.c_str(), NULL) > 0) {
|
||||
mProgram.CompileFile(scriptFile.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Make sure the file isnt already compiled before trying to compile it again
|
||||
for ( int f = mProgram->NumFilenames() - 1; f >= 0; f -- )
|
||||
{
|
||||
idStr qpath;
|
||||
qpath = fileSystem->OSPathToRelativePath ( mProgram->GetFilename ( f ) );
|
||||
qpath.BackSlashesToSlashes ( );
|
||||
if ( !qpath.Cmp ( filename ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( f < 0 )
|
||||
{
|
||||
mProgram->CompileText ( filename, mContents, false );
|
||||
}
|
||||
|
||||
mProgram->FinishCompilation ( );
|
||||
}
|
||||
catch ( idException& )
|
||||
{
|
||||
// Failed to parse the script so fail to load the file
|
||||
delete mProgram;
|
||||
mProgram = NULL;
|
||||
delete[] mContents;
|
||||
mContents = NULL;
|
||||
|
||||
// TODO: Should cache the error for the dialog box
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerScript::Reload
|
||||
|
||||
Reload the contents of the script
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerScript::Reload ( void )
|
||||
{
|
||||
return Load ( mFilename );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerScript::IsValidLine
|
||||
|
||||
Determines whether or not the given line number within the script is a valid line of code
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerScript::IsLineCode ( int linenumber )
|
||||
{
|
||||
int i;
|
||||
|
||||
assert ( mProgram );
|
||||
|
||||
// Run through all the statements in the program and see if any match the
|
||||
// linenumber that we are checking.
|
||||
for ( i = 0; i < mProgram->NumStatements ( ); i ++ )
|
||||
{
|
||||
if ( mProgram->GetStatement ( i ).linenumber == linenumber )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerScript::IsFileModified
|
||||
|
||||
Determines whether or not the file loaded for this script has been modified since
|
||||
it was loaded.
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerScript::IsFileModified ( bool updateTime )
|
||||
{
|
||||
ID_TIME_T t;
|
||||
bool result = false;
|
||||
|
||||
// Grab the filetime and shut the file down
|
||||
fileSystem->ReadFile ( mFilename, NULL, &t );
|
||||
|
||||
// Has the file been modified?
|
||||
if ( t > mModifiedTime )
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
// If updateTime is true then we will update the modified time
|
||||
// stored in the script with the files current modified time
|
||||
if ( updateTime )
|
||||
{
|
||||
mModifiedTime = t;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
78
neo/tools/debugger/DebuggerScript.h
Normal file
78
neo/tools/debugger/DebuggerScript.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef DEBUGGERSCRIPT_H_
|
||||
#define DEBUGGERSCRIPT_H_
|
||||
|
||||
class idProgram;
|
||||
class idUserInterfaceLocal;
|
||||
|
||||
class rvDebuggerScript
|
||||
{
|
||||
public:
|
||||
|
||||
rvDebuggerScript ( void );
|
||||
~rvDebuggerScript ( void );
|
||||
|
||||
bool Load ( const char* filename );
|
||||
bool Reload ( void );
|
||||
|
||||
const char* GetFilename ( void );
|
||||
const char* GetContents ( void );
|
||||
|
||||
idProgram& GetProgram ( void );
|
||||
|
||||
bool IsLineCode ( int linenumber );
|
||||
bool IsFileModified ( bool updateTime = false );
|
||||
|
||||
protected:
|
||||
|
||||
void Unload ( void );
|
||||
|
||||
idProgram* mProgram;
|
||||
idUserInterfaceLocal* mInterface;
|
||||
char* mContents;
|
||||
idStr mFilename;
|
||||
ID_TIME_T mModifiedTime;
|
||||
};
|
||||
|
||||
ID_INLINE const char* rvDebuggerScript::GetFilename ( void )
|
||||
{
|
||||
return mFilename;
|
||||
}
|
||||
|
||||
ID_INLINE const char* rvDebuggerScript::GetContents ( void )
|
||||
{
|
||||
return mContents?mContents:"";
|
||||
}
|
||||
|
||||
ID_INLINE idProgram& rvDebuggerScript::GetProgram ( void )
|
||||
{
|
||||
return *mProgram;
|
||||
}
|
||||
|
||||
#endif // DEBUGGERSCRIPT_H_
|
||||
714
neo/tools/debugger/DebuggerServer.cpp
Normal file
714
neo/tools/debugger/DebuggerServer.cpp
Normal file
@@ -0,0 +1,714 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../../game/gamesys/Event.h"
|
||||
#include "../../game/gamesys/Class.h"
|
||||
#include "../../game/script/Script_Program.h"
|
||||
#include "../../game/script/Script_Interpreter.h"
|
||||
#include "../../game/script/Script_Thread.h"
|
||||
#include "../../game/script/Script_Compiler.h"
|
||||
#include "../../framework/sync/Msg.h"
|
||||
#include "DebuggerApp.h"
|
||||
#include "DebuggerServer.h"
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::rvDebuggerServer
|
||||
================
|
||||
*/
|
||||
rvDebuggerServer::rvDebuggerServer ( )
|
||||
{
|
||||
mConnected = false;
|
||||
mBreakNext = false;
|
||||
mBreak = false;
|
||||
mBreakStepOver = false;
|
||||
mBreakStepInto = false;
|
||||
mGameThread = NULL;
|
||||
mLastStatementLine = -1;
|
||||
mBreakStepOverFunc1 = NULL;
|
||||
mBreakStepOverFunc2 = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::~rvDebuggerServer
|
||||
================
|
||||
*/
|
||||
rvDebuggerServer::~rvDebuggerServer ( )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::Initialize
|
||||
|
||||
Initialize the debugger server. This function should be called before the
|
||||
debugger server is used.
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerServer::Initialize ( void )
|
||||
{
|
||||
// Initialize the network connection
|
||||
if ( !mPort.InitForPort ( 27980 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get a copy of the game thread handle so we can suspend the thread on a break
|
||||
DuplicateHandle ( GetCurrentProcess(), GetCurrentThread ( ), GetCurrentProcess(), &mGameThread, 0, FALSE, DUPLICATE_SAME_ACCESS );
|
||||
|
||||
// Create a critical section to ensure that the shared thread
|
||||
// variables are protected
|
||||
InitializeCriticalSection ( &mCriticalSection );
|
||||
|
||||
// Server must be running on the local host on port 28980
|
||||
Sys_StringToNetAdr ( "localhost", &mClientAdr, true );
|
||||
mClientAdr.port = 27981;
|
||||
|
||||
// Attempt to let the server know we are here. The server may not be running so this
|
||||
// message will just get ignored.
|
||||
SendMessage ( DBMSG_CONNECT );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void rvDebuggerServer::OSPathToRelativePath( const char *osPath, idStr &qpath )
|
||||
{
|
||||
if ( strchr( osPath, ':' ) )
|
||||
{
|
||||
qpath = fileSystem->OSPathToRelativePath( osPath );
|
||||
}
|
||||
else
|
||||
{
|
||||
qpath = osPath;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::Shutdown
|
||||
|
||||
Shutdown the debugger server.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::Shutdown ( void )
|
||||
{
|
||||
// Let the debugger client know we are shutting down
|
||||
if ( mConnected )
|
||||
{
|
||||
SendMessage ( DBMSG_DISCONNECT );
|
||||
mConnected = false;
|
||||
}
|
||||
|
||||
mPort.Close();
|
||||
|
||||
// dont need the crit section anymore
|
||||
DeleteCriticalSection ( &mCriticalSection );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::ProcessMessages
|
||||
|
||||
Process all incoming network messages from the debugger client
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerServer::ProcessMessages ( void )
|
||||
{
|
||||
netadr_t adrFrom;
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
|
||||
// Check for pending udp packets on the debugger port
|
||||
while ( mPort.GetPacket ( adrFrom, msg.data, msg.cursize, msg.maxsize ) )
|
||||
{
|
||||
unsigned short command;
|
||||
|
||||
// Only accept packets from the debugger server for security reasons
|
||||
if ( !Sys_CompareNetAdrBase ( adrFrom, mClientAdr ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
command = (unsigned short) MSG_ReadShort ( &msg );
|
||||
|
||||
switch ( command )
|
||||
{
|
||||
case DBMSG_CONNECT:
|
||||
mConnected = true;
|
||||
SendMessage ( DBMSG_CONNECTED );
|
||||
break;
|
||||
|
||||
case DBMSG_CONNECTED:
|
||||
mConnected = true;
|
||||
break;
|
||||
|
||||
case DBMSG_DISCONNECT:
|
||||
ClearBreakpoints ( );
|
||||
Resume ( );
|
||||
mConnected = false;
|
||||
break;
|
||||
|
||||
case DBMSG_ADDBREAKPOINT:
|
||||
HandleAddBreakpoint ( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_REMOVEBREAKPOINT:
|
||||
HandleRemoveBreakpoint ( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_RESUME:
|
||||
Resume ( );
|
||||
break;
|
||||
|
||||
case DBMSG_BREAK:
|
||||
mBreakNext = true;
|
||||
break;
|
||||
|
||||
case DBMSG_STEPOVER:
|
||||
mBreakStepOver = true;
|
||||
mBreakStepOverDepth = mBreakInterpreter->GetCallstackDepth ( );
|
||||
mBreakStepOverFunc1 = mBreakInterpreter->GetCallstack()[mBreakInterpreter->GetCallstackDepth()].f;
|
||||
if ( mBreakInterpreter->GetCallstackDepth() > 0 )
|
||||
{
|
||||
mBreakStepOverFunc2 = mBreakInterpreter->GetCallstack()[mBreakInterpreter->GetCallstackDepth()-1].f;
|
||||
}
|
||||
else
|
||||
{
|
||||
mBreakStepOverFunc2 = NULL;
|
||||
}
|
||||
Resume ( );
|
||||
break;
|
||||
|
||||
case DBMSG_STEPINTO:
|
||||
mBreakStepInto = true;
|
||||
Resume ( );
|
||||
break;
|
||||
|
||||
case DBMSG_INSPECTVARIABLE:
|
||||
HandleInspectVariable ( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_INSPECTCALLSTACK:
|
||||
HandleInspectCallstack ( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_INSPECTTHREADS:
|
||||
HandleInspectThreads ( &msg );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::SendMessage
|
||||
|
||||
Send a message with no data to the debugger server.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::SendMessage ( EDebuggerMessage dbmsg )
|
||||
{
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)dbmsg );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::HandleAddBreakpoint
|
||||
|
||||
Handle the DBMSG_ADDBREAKPOINT message being sent by the debugger client. This
|
||||
message is handled by adding a new breakpoint to the breakpoint list with the
|
||||
data supplied in the message.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleAddBreakpoint ( msg_t* msg )
|
||||
{
|
||||
bool onceOnly = false;
|
||||
long lineNumber;
|
||||
long id;
|
||||
char filename[MAX_PATH];
|
||||
|
||||
// Read the breakpoint info
|
||||
onceOnly = MSG_ReadBits ( msg, 1 ) ? true : false;
|
||||
lineNumber = MSG_ReadLong ( msg );
|
||||
id = MSG_ReadLong ( msg );
|
||||
|
||||
MSG_ReadString ( msg, filename, MAX_PATH );
|
||||
|
||||
// Since breakpoints are used by both threads we need to
|
||||
// protect them with a crit section
|
||||
EnterCriticalSection ( &mCriticalSection );
|
||||
mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber, id ) );
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::HandleRemoveBreakpoint
|
||||
|
||||
Handle the DBMSG_REMOVEBREAKPOINT message being sent by the debugger client. This
|
||||
message is handled by removing the breakpoint that matches the given id from the
|
||||
list.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleRemoveBreakpoint ( msg_t* msg )
|
||||
{
|
||||
int i;
|
||||
int id;
|
||||
|
||||
// ID that we are to remove
|
||||
id = MSG_ReadLong ( msg );
|
||||
|
||||
// Since breakpoints are used by both threads we need to
|
||||
// protect them with a crit section
|
||||
EnterCriticalSection ( &mCriticalSection );
|
||||
|
||||
// Find the breakpoint that matches the given id and remove it from the list
|
||||
for ( i = 0; i < mBreakpoints.Num(); i ++ )
|
||||
{
|
||||
if ( mBreakpoints[i]->GetID ( ) == id )
|
||||
{
|
||||
delete mBreakpoints[i];
|
||||
mBreakpoints.RemoveIndex ( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::MSG_WriteCallstackFunc
|
||||
|
||||
Writes a single callstack entry to the given message
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::MSG_WriteCallstackFunc ( msg_t* msg, const prstack_t* stack )
|
||||
{
|
||||
const statement_t* st;
|
||||
const function_t* func;
|
||||
|
||||
func = stack->f;
|
||||
|
||||
// If the function is unknown then just fill in with default data.
|
||||
if ( !func )
|
||||
{
|
||||
MSG_WriteString ( msg, "<UNKNOWN>" );
|
||||
MSG_WriteString ( msg, "<UNKNOWN>" );
|
||||
MSG_WriteLong ( msg, 0 );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteString ( msg, va("%s( ??? )", func->Name() ) );
|
||||
}
|
||||
|
||||
// Use the calling statement as the filename and linenumber where
|
||||
// the call was made from
|
||||
st = &mBreakProgram->GetStatement ( stack->s );
|
||||
if ( st )
|
||||
{
|
||||
idStr qpath;
|
||||
OSPathToRelativePath(mBreakProgram->GetFilename( st->file ), qpath);
|
||||
qpath.BackSlashesToSlashes ( );
|
||||
MSG_WriteString ( msg, qpath );
|
||||
MSG_WriteLong ( msg, st->linenumber );
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteString ( msg, "<UNKNOWN>" );
|
||||
MSG_WriteLong ( msg, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::HandleInspectCallstack
|
||||
|
||||
Handle an incoming inspect callstack message by sending a message
|
||||
back to the client with the callstack data.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleInspectCallstack ( msg_t* in_msg )
|
||||
{
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
int i;
|
||||
prstack_t temp;
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTCALLSTACK );
|
||||
|
||||
MSG_WriteShort ( &msg, (int)mBreakInterpreter->GetCallstackDepth ( ) );
|
||||
|
||||
// write out the current function
|
||||
temp.f = mBreakInterpreter->GetCurrentFunction ( );
|
||||
temp.s = 0;
|
||||
temp.stackbase = 0;
|
||||
MSG_WriteCallstackFunc ( &msg, &temp );
|
||||
|
||||
// Run through all of the callstack and write each to the msg
|
||||
for ( i = mBreakInterpreter->GetCallstackDepth ( ) - 1; i > 0; i -- )
|
||||
{
|
||||
MSG_WriteCallstackFunc ( &msg, mBreakInterpreter->GetCallstack ( ) + i );
|
||||
}
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::HandleInspectThreads
|
||||
|
||||
Send the list of the current threads in the interpreter back to the debugger client
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleInspectThreads ( msg_t* in_msg )
|
||||
{
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
int i;
|
||||
|
||||
// Initialize the message
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTTHREADS );
|
||||
|
||||
// Write the number of threads to the message
|
||||
MSG_WriteShort ( &msg, (int)idThread::GetThreads().Num() );
|
||||
|
||||
// Loop through all of the threads and write their name and number to the message
|
||||
for ( i = 0; i < idThread::GetThreads().Num(); i ++ )
|
||||
{
|
||||
idThread* thread = idThread::GetThreads()[i];
|
||||
|
||||
MSG_WriteString ( &msg, thread->GetThreadName ( ) );
|
||||
MSG_WriteLong ( &msg, thread->GetThreadNum ( ) );
|
||||
|
||||
MSG_WriteBits ( &msg, (int)(thread == mBreakInterpreter->GetThread ( )), 1 );
|
||||
MSG_WriteBits ( &msg, (int)thread->IsDoneProcessing(), 1 );
|
||||
MSG_WriteBits ( &msg, (int)thread->IsWaiting(), 1 );
|
||||
MSG_WriteBits ( &msg, (int)thread->IsDying(), 1 );
|
||||
}
|
||||
|
||||
// Send off the inspect threads packet to the debugger client
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::HandleInspectVariable
|
||||
|
||||
Respondes to a request from the debugger client to inspect the value of a given variable
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleInspectVariable ( msg_t* in_msg )
|
||||
{
|
||||
char varname[256];
|
||||
int scopeDepth;
|
||||
|
||||
if ( !mBreak )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scopeDepth = (short)MSG_ReadShort ( in_msg );
|
||||
MSG_ReadString ( in_msg, varname, 256 );
|
||||
|
||||
idStr varvalue;
|
||||
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
// Initialize the message
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTVARIABLE );
|
||||
|
||||
if ( !mBreakInterpreter->GetRegisterValue ( varname, varvalue, scopeDepth ) )
|
||||
{
|
||||
varvalue = "???";
|
||||
}
|
||||
|
||||
MSG_WriteShort ( &msg, (short)scopeDepth );
|
||||
MSG_WriteString ( &msg, varname );
|
||||
MSG_WriteString ( &msg, varvalue );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::CheckBreakpoints
|
||||
|
||||
Check to see if any breakpoints have been hit. This includes "break next",
|
||||
"step into", and "step over" break points
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer )
|
||||
{
|
||||
const statement_t* st;
|
||||
const char* filename;
|
||||
int i;
|
||||
|
||||
if ( !mConnected ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab the current statement and the filename that it came from
|
||||
st = &program->GetStatement ( instructionPointer );
|
||||
filename = program->GetFilename ( st->file );
|
||||
|
||||
// Operate on lines, not statements
|
||||
if ( mLastStatementLine == st->linenumber && mLastStatementFile == st->file )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the last visited line and file so we can prevent
|
||||
// double breaks on lines with more than one statement
|
||||
mLastStatementFile = idStr( st->file );
|
||||
mLastStatementLine = st->linenumber;
|
||||
|
||||
// Reset stepping when the last function on the callstack is returned from
|
||||
if ( st->op == OP_RETURN && interpreter->GetCallstackDepth ( ) <= 1 )
|
||||
{
|
||||
mBreakStepOver = false;
|
||||
mBreakStepInto = false;
|
||||
}
|
||||
|
||||
// See if we are supposed to break on the next script line
|
||||
if ( mBreakNext )
|
||||
{
|
||||
Break ( interpreter, program, instructionPointer );
|
||||
return;
|
||||
}
|
||||
|
||||
// Only break on the same callstack depth and thread as the break over
|
||||
if ( mBreakStepOver )
|
||||
{
|
||||
if ( ( interpreter->GetCurrentFunction ( ) == mBreakStepOverFunc1 ||
|
||||
interpreter->GetCurrentFunction ( ) == mBreakStepOverFunc2 )&&
|
||||
( interpreter->GetCallstackDepth ( ) <= mBreakStepOverDepth ) )
|
||||
{
|
||||
Break ( interpreter, program, instructionPointer );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// See if we are supposed to break on the next line
|
||||
if ( mBreakStepInto )
|
||||
{
|
||||
// Break
|
||||
Break ( interpreter, program, instructionPointer );
|
||||
return;
|
||||
}
|
||||
|
||||
idStr qpath;
|
||||
OSPathToRelativePath(filename,qpath);
|
||||
qpath.BackSlashesToSlashes ( );
|
||||
|
||||
EnterCriticalSection ( &mCriticalSection );
|
||||
|
||||
// Check all the breakpoints
|
||||
for ( i = 0; i < mBreakpoints.Num ( ); i ++ )
|
||||
{
|
||||
rvDebuggerBreakpoint* bp = mBreakpoints[i];
|
||||
|
||||
// Skip if not match of the line number
|
||||
if ( st->linenumber != bp->GetLineNumber ( ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if no match of the filename
|
||||
if ( idStr::Icmp ( bp->GetFilename(), qpath ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Pop out of the critical section so we dont get stuck
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
|
||||
// We hit a breakpoint, so break
|
||||
Break ( interpreter, program, instructionPointer );
|
||||
|
||||
// Back into the critical section since we are going to have to leave it
|
||||
EnterCriticalSection ( &mCriticalSection );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::Break
|
||||
|
||||
Halt execution of the game threads and inform the debugger client that
|
||||
the game has been halted
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer )
|
||||
{
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
const statement_t* st;
|
||||
const char* filename;
|
||||
|
||||
// Clear all the break types
|
||||
mBreakStepOver = false;
|
||||
mBreakStepInto = false;
|
||||
mBreakNext = false;
|
||||
|
||||
// Grab the current statement and the filename that it came from
|
||||
st = &program->GetStatement ( instructionPointer );
|
||||
filename = program->GetFilename ( st->file );
|
||||
|
||||
idStr qpath;
|
||||
OSPathToRelativePath(filename, qpath);
|
||||
qpath.BackSlashesToSlashes ( );
|
||||
|
||||
// Give the mouse cursor back to the world
|
||||
Sys_GrabMouseCursor( false );
|
||||
|
||||
// Set the break variable so we know the main thread is stopped
|
||||
mBreak = true;
|
||||
mBreakProgram = program;
|
||||
mBreakInterpreter = interpreter;
|
||||
mBreakInstructionPointer = instructionPointer;
|
||||
|
||||
// Inform the debugger of the breakpoint hit
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_BREAK );
|
||||
MSG_WriteLong ( &msg, st->linenumber );
|
||||
MSG_WriteString ( &msg, qpath );
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
|
||||
// Suspend the game thread. Since this will be called from within the main game thread
|
||||
// execution wont return until after the thread is resumed
|
||||
SuspendThread ( mGameThread );
|
||||
|
||||
// Let the debugger client know that we have started back up again
|
||||
SendMessage ( DBMSG_RESUMED );
|
||||
|
||||
// This is to give some time between the keypress that
|
||||
// told us to resume and the setforeground window. Otherwise the quake window
|
||||
// would just flash
|
||||
Sleep ( 150 );
|
||||
|
||||
// Bring the window back to the foreground
|
||||
SetForegroundWindow ( win32.hWnd );
|
||||
SetActiveWindow ( win32.hWnd );
|
||||
UpdateWindow ( win32.hWnd );
|
||||
SetFocus ( win32.hWnd );
|
||||
|
||||
// Give the mouse cursor back to the game
|
||||
Sys_GrabMouseCursor( true );
|
||||
|
||||
// Clear all commands that were generated before we went into suspended mode. This is
|
||||
// to ensure we dont have mouse downs with no ups because the context was changed.
|
||||
idKeyInput::ClearStates();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::Resume
|
||||
|
||||
Resume execution of the game.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::Resume ( void )
|
||||
{
|
||||
// Cant resume if not paused
|
||||
if ( !mBreak )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mBreak = false;
|
||||
|
||||
// Start the game thread back up
|
||||
ResumeThread ( mGameThread );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::ClearBreakpoints
|
||||
|
||||
Remove all known breakpoints
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::ClearBreakpoints ( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < mBreakpoints.Num(); i ++ )
|
||||
{
|
||||
delete mBreakpoints[i];
|
||||
}
|
||||
|
||||
mBreakpoints.Clear ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::Print
|
||||
|
||||
Sends a console print message over to the debugger client
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::Print ( const char* text )
|
||||
{
|
||||
if ( !mConnected )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_PRINT );
|
||||
MSG_WriteString ( &msg, text );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
}
|
||||
133
neo/tools/debugger/DebuggerServer.h
Normal file
133
neo/tools/debugger/DebuggerServer.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef DEBUGGERSERVER_H_
|
||||
#define DEBUGGERSERVER_H_
|
||||
|
||||
#ifndef DEBUGGERMESSAGES_H_
|
||||
#include "DebuggerMessages.h"
|
||||
#endif
|
||||
|
||||
#ifndef DEBUGGERBREAKPOINT_H_
|
||||
#include "DebuggerBreakpoint.h"
|
||||
#endif
|
||||
|
||||
#ifndef __GAME_LOCAL_H__
|
||||
#include "../../game/Game.h"
|
||||
#endif
|
||||
|
||||
class idInterpreter;
|
||||
class idProgram;
|
||||
|
||||
class rvDebuggerServer
|
||||
{
|
||||
public:
|
||||
|
||||
rvDebuggerServer ( );
|
||||
~rvDebuggerServer ( );
|
||||
|
||||
bool Initialize ( void );
|
||||
void Shutdown ( void );
|
||||
|
||||
bool ProcessMessages ( void );
|
||||
|
||||
bool IsConnected ( void );
|
||||
|
||||
void CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer );
|
||||
|
||||
void Print ( const char* text );
|
||||
|
||||
void OSPathToRelativePath( const char *osPath, idStr &qpath );
|
||||
|
||||
protected:
|
||||
|
||||
// protected member variables
|
||||
bool mConnected;
|
||||
netadr_t mClientAdr;
|
||||
idPort mPort;
|
||||
idList<rvDebuggerBreakpoint*> mBreakpoints;
|
||||
CRITICAL_SECTION mCriticalSection;
|
||||
|
||||
HANDLE mGameThread;
|
||||
|
||||
bool mBreak;
|
||||
bool mBreakNext;
|
||||
bool mBreakStepOver;
|
||||
bool mBreakStepInto;
|
||||
int mBreakStepOverDepth;
|
||||
const function_t* mBreakStepOverFunc1;
|
||||
const function_t* mBreakStepOverFunc2;
|
||||
idProgram* mBreakProgram;
|
||||
int mBreakInstructionPointer;
|
||||
idInterpreter* mBreakInterpreter;
|
||||
|
||||
idStr mLastStatementFile;
|
||||
int mLastStatementLine;
|
||||
|
||||
private:
|
||||
|
||||
void ClearBreakpoints ( void );
|
||||
|
||||
void Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer );
|
||||
void Resume ( void );
|
||||
|
||||
void SendMessage ( EDebuggerMessage dbmsg );
|
||||
void SendPacket ( void* data, int datasize );
|
||||
|
||||
// Message handlers
|
||||
void HandleAddBreakpoint ( msg_t* msg );
|
||||
void HandleRemoveBreakpoint ( msg_t* msg );
|
||||
void HandleResume ( msg_t* msg );
|
||||
void HandleInspectVariable ( msg_t* msg );
|
||||
void HandleInspectCallstack ( msg_t* msg );
|
||||
void HandleInspectThreads ( msg_t* msg );
|
||||
|
||||
// MSG helper routines
|
||||
void MSG_WriteCallstackFunc ( msg_t* msg, const prstack_t* stack );
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::IsConnected
|
||||
================
|
||||
*/
|
||||
ID_INLINE bool rvDebuggerServer::IsConnected ( void )
|
||||
{
|
||||
return mConnected;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::SendPacket
|
||||
================
|
||||
*/
|
||||
ID_INLINE void rvDebuggerServer::SendPacket ( void* data, int size )
|
||||
{
|
||||
mPort.SendPacket ( mClientAdr, data, size );
|
||||
}
|
||||
|
||||
#endif // DEBUGGERSERVER_H_
|
||||
2373
neo/tools/debugger/DebuggerWindow.cpp
Normal file
2373
neo/tools/debugger/DebuggerWindow.cpp
Normal file
File diff suppressed because it is too large
Load Diff
184
neo/tools/debugger/DebuggerWindow.h
Normal file
184
neo/tools/debugger/DebuggerWindow.h
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef DEBUGGERWINDOW_H_
|
||||
#define DEBUGGERWINDOW_H_
|
||||
|
||||
#ifndef DEBUGGERSCRIPT_H_
|
||||
#include "DebuggerScript.h"
|
||||
#endif
|
||||
|
||||
class rvDebuggerWatch
|
||||
{
|
||||
public:
|
||||
|
||||
idStr mVariable;
|
||||
idStr mValue;
|
||||
bool mModified;
|
||||
};
|
||||
|
||||
typedef idList<rvDebuggerWatch*> rvDebuggerWatchList;
|
||||
|
||||
class rvDebuggerClient;
|
||||
|
||||
class rvDebuggerWindow
|
||||
{
|
||||
public:
|
||||
|
||||
rvDebuggerWindow ( );
|
||||
~rvDebuggerWindow ( );
|
||||
|
||||
bool Create ( HINSTANCE hInstance );
|
||||
|
||||
static bool Activate ( void );
|
||||
|
||||
void ProcessNetMessage ( msg_t* msg );
|
||||
|
||||
void Printf ( const char* format, ... );
|
||||
|
||||
HWND GetWindow ( void );
|
||||
|
||||
void AddWatch ( const char* name, bool update = true );
|
||||
|
||||
HINSTANCE GetInstance ( void );
|
||||
|
||||
protected:
|
||||
|
||||
bool FindPrev ( const char* text = NULL );
|
||||
bool FindNext ( const char* text = NULL );
|
||||
|
||||
void UpdateWatch ( void );
|
||||
void UpdateWindowMenu ( void );
|
||||
void UpdateScript ( void );
|
||||
void UpdateToolbar ( void );
|
||||
void UpdateTitle ( void );
|
||||
void UpdateCallstack ( void );
|
||||
void UpdateRecentFiles ( void );
|
||||
bool OpenScript ( const char* filename, int lineNumber = -1 );
|
||||
void EnableWindows ( bool state );
|
||||
|
||||
int GetSelectedText ( idStr& text );
|
||||
|
||||
void ToggleBreakpoint ( void );
|
||||
|
||||
HWND mWnd;
|
||||
HWND mWndScript;
|
||||
HWND mWndOutput;
|
||||
HWND mWndMargin;
|
||||
HWND mWndTabs;
|
||||
HWND mWndBorder;
|
||||
HWND mWndConsole;
|
||||
HWND mWndCallstack;
|
||||
HWND mWndWatch;
|
||||
HWND mWndThreads;
|
||||
HWND mWndToolTips;
|
||||
HWND mWndToolbar;
|
||||
|
||||
HMENU mRecentFileMenu;
|
||||
int mRecentFileInsertPos;
|
||||
|
||||
WNDPROC mOldWatchProc;
|
||||
WNDPROC mOldScriptProc;
|
||||
idStr mTooltipVar;
|
||||
idStr mTooltipValue;
|
||||
|
||||
HINSTANCE mInstance;
|
||||
HIMAGELIST mImageList;
|
||||
|
||||
RECT mSplitterRect;
|
||||
bool mSplitterDrag;
|
||||
|
||||
idList<rvDebuggerScript*> mScripts;
|
||||
int mActiveScript;
|
||||
int mLastActiveScript;
|
||||
int mCurrentStackDepth;
|
||||
|
||||
HMENU mWindowMenu;
|
||||
int mWindowMenuPos;
|
||||
|
||||
int mZoomScaleNum;
|
||||
int mZoomScaleDem;
|
||||
int mMarginSize;
|
||||
|
||||
idStr mFind;
|
||||
|
||||
rvDebuggerClient* mClient;
|
||||
|
||||
rvDebuggerWatchList mWatches;
|
||||
|
||||
private:
|
||||
|
||||
bool RegisterClass ( void );
|
||||
void CreateToolbar ( void );
|
||||
bool InitRecentFiles ( void );
|
||||
|
||||
int HandleInitMenu ( WPARAM wParam, LPARAM lParam );
|
||||
int HandleCommand ( WPARAM wParam, LPARAM lParam );
|
||||
int HandleCreate ( WPARAM wparam, LPARAM lparam );
|
||||
int HandleActivate ( WPARAM wparam, LPARAM lparam );
|
||||
int HandleDrawItem ( WPARAM wparam, LPARAM lparam );
|
||||
void HandleTooltipGetDispInfo ( WPARAM wparam, LPARAM lparam );
|
||||
|
||||
static LRESULT CALLBACK WndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static LRESULT CALLBACK MarginWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static LRESULT CALLBACK ScriptWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static INT_PTR CALLBACK AboutDlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static int CALLBACK ScriptWordBreakProc ( LPTSTR text, int current, int max, int action );
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerWindow::GetWindow
|
||||
================
|
||||
*/
|
||||
ID_INLINE HWND rvDebuggerWindow::GetWindow ( void )
|
||||
{
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerWindow::UpdateToolbar
|
||||
================
|
||||
*/
|
||||
ID_INLINE void rvDebuggerWindow::UpdateToolbar ( void )
|
||||
{
|
||||
HandleInitMenu ( (WPARAM)GetMenu ( mWnd ), 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerWindow::GetInstance
|
||||
================
|
||||
*/
|
||||
ID_INLINE HINSTANCE rvDebuggerWindow::GetInstance ( void )
|
||||
{
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
#endif // DEBUGGERWINDOW_H_
|
||||
|
||||
235
neo/tools/debugger/debugger.cpp
Normal file
235
neo/tools/debugger/debugger.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../../sys/win32/rc/debugger_resource.h"
|
||||
#include "DebuggerApp.h"
|
||||
#include "DebuggerServer.h"
|
||||
|
||||
DWORD CALLBACK DebuggerThread ( LPVOID param );
|
||||
|
||||
rvDebuggerApp gDebuggerApp;
|
||||
HWND gDebuggerWindow = NULL;
|
||||
bool gDebuggerSuspend = false;
|
||||
bool gDebuggerConnnected = false;
|
||||
HANDLE gDebuggerGameThread = NULL;
|
||||
|
||||
rvDebuggerServer* gDebuggerServer = NULL;
|
||||
HANDLE gDebuggerServerThread = NULL;
|
||||
DWORD gDebuggerServerThreadID = 0;
|
||||
bool gDebuggerServerQuit = false;
|
||||
|
||||
/*
|
||||
================
|
||||
DebuggerMain
|
||||
|
||||
Main entry point for the debugger application
|
||||
================
|
||||
*/
|
||||
void DebuggerClientInit( const char *cmdline )
|
||||
{
|
||||
// See if the debugger is already running
|
||||
if ( rvDebuggerWindow::Activate ( ) )
|
||||
{
|
||||
goto DebuggerClientInitDone;
|
||||
}
|
||||
|
||||
if ( !gDebuggerApp.Initialize ( win32.hInstance ) )
|
||||
{
|
||||
goto DebuggerClientInitDone;
|
||||
}
|
||||
|
||||
gDebuggerApp.Run ( );
|
||||
|
||||
DebuggerClientInitDone:
|
||||
|
||||
common->Quit();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DebuggerLaunch
|
||||
|
||||
Launches another instance of the running executable with +debugger appended
|
||||
to the end to indicate that the debugger should start up.
|
||||
================
|
||||
*/
|
||||
void DebuggerClientLaunch ( void )
|
||||
{
|
||||
if ( renderSystem->IsFullScreen() ) {
|
||||
common->Printf( "Cannot run the script debugger in fullscreen mode.\n"
|
||||
"Set r_fullscreen to 0 and vid_restart.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// See if the debugger is already running
|
||||
if ( rvDebuggerWindow::Activate ( ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
char exeFile[MAX_PATH];
|
||||
char curDir[MAX_PATH];
|
||||
|
||||
STARTUPINFO startup;
|
||||
PROCESS_INFORMATION process;
|
||||
|
||||
ZeroMemory ( &startup, sizeof(startup) );
|
||||
startup.cb = sizeof(startup);
|
||||
|
||||
GetCurrentDirectory ( MAX_PATH, curDir );
|
||||
|
||||
GetModuleFileName ( NULL, exeFile, MAX_PATH );
|
||||
const char* s = va("%s +set fs_game %s +set fs_cdpath %s +debugger", exeFile, cvarSystem->GetCVarString( "fs_game" ), cvarSystem->GetCVarString( "fs_cdpath" ) );
|
||||
CreateProcess ( NULL, (LPSTR)s,
|
||||
NULL, NULL, FALSE, 0, NULL, curDir, &startup, &process );
|
||||
|
||||
CloseHandle ( process.hThread );
|
||||
CloseHandle ( process.hProcess );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DebuggerServerThread
|
||||
|
||||
Thread proc for the debugger server
|
||||
================
|
||||
*/
|
||||
DWORD CALLBACK DebuggerServerThread ( LPVOID param )
|
||||
{
|
||||
assert ( gDebuggerServer );
|
||||
|
||||
while ( !gDebuggerServerQuit )
|
||||
{
|
||||
gDebuggerServer->ProcessMessages ( );
|
||||
Sleep ( 1 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DebuggerServerInit
|
||||
|
||||
Starts up the debugger server
|
||||
================
|
||||
*/
|
||||
bool DebuggerServerInit ( void )
|
||||
{
|
||||
// Dont do this if we are in the debugger already
|
||||
if ( com_editors & EDITOR_DEBUGGER )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate the new debugger server
|
||||
gDebuggerServer = new rvDebuggerServer;
|
||||
if ( !gDebuggerServer )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the debugger server
|
||||
if ( !gDebuggerServer->Initialize ( ) )
|
||||
{
|
||||
delete gDebuggerServer;
|
||||
gDebuggerServer = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start the debugger server thread
|
||||
gDebuggerServerThread = CreateThread ( NULL, 0, DebuggerServerThread, 0, 0, &gDebuggerServerThreadID );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DebuggerServerShutdown
|
||||
|
||||
Shuts down the debugger server
|
||||
================
|
||||
*/
|
||||
void DebuggerServerShutdown ( void )
|
||||
{
|
||||
if ( gDebuggerServerThread )
|
||||
{
|
||||
// Signal the debugger server to quit
|
||||
gDebuggerServerQuit = true;
|
||||
|
||||
// Wait for the thread to finish
|
||||
WaitForSingleObject ( gDebuggerServerThread, INFINITE );
|
||||
|
||||
// Shutdown the server now
|
||||
gDebuggerServer->Shutdown();
|
||||
|
||||
delete gDebuggerServer;
|
||||
gDebuggerServer = NULL;
|
||||
|
||||
// Cleanup the thread handle
|
||||
CloseHandle ( gDebuggerServerThread );
|
||||
gDebuggerServerThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DebuggerServerCheckBreakpoint
|
||||
|
||||
Check to see if there is a breakpoint associtated with this statement
|
||||
================
|
||||
*/
|
||||
void DebuggerServerCheckBreakpoint ( idInterpreter* interpreter, idProgram* program, int instructionPointer )
|
||||
{
|
||||
if ( !gDebuggerServer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gDebuggerServer->CheckBreakpoints ( interpreter, program, instructionPointer );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DebuggerServerPrint
|
||||
|
||||
Sends a print message to the debugger client
|
||||
================
|
||||
*/
|
||||
void DebuggerServerPrint ( const char* text )
|
||||
{
|
||||
if ( !gDebuggerServer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gDebuggerServer->Print ( text );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user