Merge branch 'master' of https://bitbucket.org/mrexodia/x64_dbg
Conflicts: x64_dbg_dbg/debugger.cpp x64_dbg_dbg/debugger_commands.cpp x64_dbg_dbg/symbolinfo.h x64_dbg_dbg/thread.h
This commit is contained in:
commit
c1115bb203
|
@ -1102,6 +1102,10 @@ BRIDGE_IMPEXP void GuiUpdateCallStack()
|
|||
_gui_sendmessage(GUI_UPDATE_CALLSTACK, 0, 0);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP void GuiLoadSourceFile(const char* path, int line)
|
||||
{
|
||||
_gui_sendmessage(GUI_LOAD_SOURCE_FILE, (void*)path, (void*)line);
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
|
|
|
@ -501,6 +501,12 @@ typedef struct
|
|||
#endif
|
||||
} REGISTERCONTEXT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD code;
|
||||
const char* name;
|
||||
} LASTERROR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
REGISTERCONTEXT regcontext;
|
||||
|
@ -510,6 +516,7 @@ typedef struct
|
|||
MXCSRFIELDS MxCsrFields;
|
||||
X87STATUSWORDFIELDS x87StatusWordFields;
|
||||
X87CONTROLWORDFIELDS x87ControlWordFields;
|
||||
LASTERROR lastError;
|
||||
} REGDUMP;
|
||||
|
||||
typedef struct
|
||||
|
@ -749,7 +756,8 @@ typedef enum
|
|||
GUI_UPDATE_CALLSTACK, // param1=unused, param2=unused
|
||||
GUI_SYMBOL_REFRESH_CURRENT, // param1=unused, param2=unused
|
||||
GUI_UPDATE_MEMORY_VIEW, // param1=unused, param2=unused
|
||||
GUI_REF_INITIALIZE // param1=const char* name param2=unused
|
||||
GUI_REF_INITIALIZE, // param1=const char* name, param2=unused
|
||||
GUI_LOAD_SOURCE_FILE // param1=const char* path, param2=line
|
||||
} GUIMSG;
|
||||
|
||||
//GUI structures
|
||||
|
@ -826,6 +834,7 @@ BRIDGE_IMPEXP void GuiRepaintTableView();
|
|||
BRIDGE_IMPEXP void GuiUpdatePatches();
|
||||
BRIDGE_IMPEXP void GuiUpdateCallStack();
|
||||
BRIDGE_IMPEXP void GuiUpdateMemoryView();
|
||||
BRIDGE_IMPEXP void GuiLoadSourceFile(const char* path, int line);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "bookmark.h"
|
||||
#include "function.h"
|
||||
#include "loop.h"
|
||||
#include "error.h"
|
||||
|
||||
static bool bOnlyCipAutoComments = false;
|
||||
|
||||
|
@ -496,6 +497,10 @@ extern "C" DLL_EXPORT bool _dbg_getregdump(REGDUMP* regdump)
|
|||
GetMxCsrFields(& (regdump->MxCsrFields), regdump->regcontext.MxCsr);
|
||||
Getx87ControlWordFields(& (regdump->x87ControlWordFields), regdump->regcontext.x87fpu.ControlWord);
|
||||
Getx87StatusWordFields(& (regdump->x87StatusWordFields), regdump->regcontext.x87fpu.StatusWord);
|
||||
LASTERROR lastError;
|
||||
lastError.code = ThreadGetLastError(ThreadGetId(hActiveThread));
|
||||
lastError.name = ErrorCodeToName(lastError.code);
|
||||
regdump->lastError = lastError;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -737,6 +742,7 @@ extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* par
|
|||
bOnlyCipAutoComments = settingboolget("Disassembler", "OnlyCipAutoComments");
|
||||
bListAllPages = settingboolget("Engine", "ListAllPages");
|
||||
bUndecorateSymbolNames = settingboolget("Engine", "UndecorateSymbolNames");
|
||||
bEnableSourceDebugging = settingboolget("Engine", "EnableSourceDebugging");
|
||||
|
||||
uint setting;
|
||||
if(BridgeSettingGetUint("Engine", "BreakpointType", &setting))
|
||||
|
|
|
@ -1,296 +0,0 @@
|
|||
/**
|
||||
\file argument.cpp
|
||||
\brief Implements the argument class.
|
||||
*/
|
||||
|
||||
#include "argument.h"
|
||||
#include "console.h"
|
||||
|
||||
/*
|
||||
formatarg:
|
||||
01) remove prepended spaces
|
||||
02) get command (first space) and lowercase
|
||||
03) get arguments
|
||||
04) remove double quotes (from arguments)
|
||||
05) temp. remove double backslash
|
||||
06) remove prepended/appended non-escaped commas and spaces (from arguments)
|
||||
a) prepended
|
||||
b) appended
|
||||
07) get quote count, ignore escaped (from arguments)
|
||||
08) process quotes (from arguments):
|
||||
a) zero quotes
|
||||
b) restore double backslash
|
||||
c) escape commas and spaces
|
||||
09) temp. remove double backslash
|
||||
10) remove unescaped double commas (from arguments)
|
||||
11) remove unescaped spaces (from arguments)
|
||||
12) restore double backslash
|
||||
13) combine formatted arguments and command
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Formats a command string (see source code for more information).
|
||||
\param [in,out] Command to format.
|
||||
*/
|
||||
void argformat(char* cmd)
|
||||
{
|
||||
if(strlen(cmd) >= deflen)
|
||||
return;
|
||||
|
||||
char command_[deflen] = "";
|
||||
char* command = command_;
|
||||
strcpy_s(command, deflen, cmd);
|
||||
while(*command == ' ')
|
||||
command++;
|
||||
|
||||
int len = (int)strlen(command);
|
||||
int start = 0;
|
||||
for(int i = 0; i < len; i++)
|
||||
if(command[i] == ' ')
|
||||
{
|
||||
command[i] = 0;
|
||||
start = i + 1;
|
||||
break;
|
||||
}
|
||||
if(!start)
|
||||
start = len;
|
||||
|
||||
char arguments_[deflen] = "";
|
||||
char* arguments = arguments_;
|
||||
strcpy_s(arguments, deflen, command + start);
|
||||
|
||||
char temp[deflen] = "";
|
||||
len = (int)strlen(arguments);
|
||||
for(int i = 0, j = 0; i < len; i++)
|
||||
{
|
||||
if(arguments[i] == '"' and arguments[i + 1] == '"') //TODO: fix this
|
||||
i += 2;
|
||||
j += sprintf(temp + j, "%c", arguments[i]);
|
||||
}
|
||||
strcpy_s(arguments, deflen, temp);
|
||||
|
||||
len = (int)strlen(arguments);
|
||||
for(int i = 0; i < len; i++)
|
||||
if(arguments[i] == '\\' and arguments[i + 1] == '\\')
|
||||
{
|
||||
arguments[i] = 1;
|
||||
arguments[i + 1] = 1;
|
||||
}
|
||||
|
||||
while((*arguments == ',' or * arguments == ' ') and * (arguments - 1) != '\\')
|
||||
arguments++;
|
||||
len = (int)strlen(arguments);
|
||||
while((arguments[len - 1] == ' ' or arguments[len - 1] == ',') and arguments[len - 2] != '\\')
|
||||
len--;
|
||||
arguments[len] = 0;
|
||||
|
||||
len = (int)strlen(arguments);
|
||||
int quote_count = 0;
|
||||
for(int i = 0; i < len; i++)
|
||||
if(arguments[i] == '"')
|
||||
quote_count++;
|
||||
|
||||
if(!(quote_count % 2))
|
||||
{
|
||||
for(int i = 0; i < len; i++)
|
||||
if(arguments[i] == '"')
|
||||
arguments[i] = 0;
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
if(arguments[i] == 1 and (i < len - 1 and arguments[i + 1] == 1))
|
||||
{
|
||||
arguments[i] = '\\';
|
||||
arguments[i + 1] = '\\';
|
||||
}
|
||||
|
||||
for(int i = 0, j = 0; i < len; i++)
|
||||
{
|
||||
if(!arguments[i])
|
||||
{
|
||||
i++;
|
||||
int len2 = (int)strlen(arguments + i);
|
||||
for(int k = 0; k < len2; k++)
|
||||
{
|
||||
if(arguments[i + k] == ',' or arguments[i + k] == ' ' or arguments[i + k] == '\\')
|
||||
j += sprintf(temp + j, "\\%c", arguments[i + k]);
|
||||
else
|
||||
j += sprintf(temp + j, "%c", arguments[i + k]);
|
||||
}
|
||||
i += len2;
|
||||
}
|
||||
else
|
||||
j += sprintf(temp + j, "%c", arguments[i]);
|
||||
}
|
||||
arguments = arguments_;
|
||||
strcpy_s(arguments, deflen, temp);
|
||||
}
|
||||
len = (int)strlen(arguments);
|
||||
for(int i = 0; i < len; i++)
|
||||
if(arguments[i] == '\\' and arguments[i + 1] == '\\')
|
||||
{
|
||||
arguments[i] = 1;
|
||||
arguments[i + 1] = 1;
|
||||
}
|
||||
len = (int)strlen(arguments);
|
||||
for(int i = 0, j = 0; i < len; i++)
|
||||
{
|
||||
if(arguments[i] == ',' and arguments[i + 1] == ',')
|
||||
i += 2;
|
||||
j += sprintf(temp + j, "%c", arguments[i]);
|
||||
}
|
||||
strcpy_s(arguments, deflen, temp);
|
||||
|
||||
len = (int)strlen(arguments);
|
||||
for(int i = 0, j = 0; i < len; i++)
|
||||
{
|
||||
while(arguments[i] == ' ' and arguments[i - 1] != '\\')
|
||||
i++;
|
||||
j += sprintf(temp + j, "%c", arguments[i]);
|
||||
}
|
||||
strcpy_s(arguments, deflen, temp);
|
||||
|
||||
len = (int)strlen(arguments);
|
||||
for(int i = 0; i < len; i++)
|
||||
if(arguments[i] == 1 and arguments[i + 1] == 1)
|
||||
{
|
||||
arguments[i] = '\\';
|
||||
arguments[i + 1] = '\\';
|
||||
}
|
||||
|
||||
if(strlen(arguments))
|
||||
sprintf(cmd, "%s %s", command, arguments);
|
||||
else
|
||||
strcpy_s(cmd, deflen, command);
|
||||
}
|
||||
|
||||
/*
|
||||
1) remove double backslash
|
||||
2) count unescaped commas
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Gets the argument count from a command formatted by argformat().
|
||||
\param cmd The command to get the argument count from.
|
||||
\return The argument count.
|
||||
*/
|
||||
int arggetcount(const char* cmd)
|
||||
{
|
||||
int len = (int)strlen(cmd);
|
||||
if(!len or len >= deflen)
|
||||
return -1;
|
||||
|
||||
int arg_count = 0;
|
||||
|
||||
int start = 0;
|
||||
while(cmd[start] != ' ' and start < len)
|
||||
start++;
|
||||
if(start == len)
|
||||
return arg_count;
|
||||
arg_count = 1;
|
||||
char temp_[deflen] = "";
|
||||
char* temp = temp_ + 1;
|
||||
strcpy_s(temp, deflen - 1, cmd);
|
||||
for(int i = start; i < len; i++)
|
||||
if(temp[i] == '\\' and (i < len - 1 and temp[i + 1] == '\\'))
|
||||
{
|
||||
temp[i] = 1;
|
||||
temp[i + 1] = 1;
|
||||
}
|
||||
|
||||
for(int i = start; i < len; i++)
|
||||
{
|
||||
if(temp[i] == ',' and temp[i - 1] != '\\')
|
||||
arg_count++;
|
||||
}
|
||||
return arg_count;
|
||||
}
|
||||
|
||||
/*
|
||||
1) get arg count
|
||||
2) remove double backslash
|
||||
3) zero non-escaped commas
|
||||
4) restore double backslash
|
||||
5) handle escape characters
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Gets an argument from a command.
|
||||
\param cmd The command to get the argument from.
|
||||
\param [out] Buffer of size #deflen.
|
||||
\param arg_num The zero-based argument number to retrieve.
|
||||
\param optional true if the argument is optional. When false there will be error messages on the console. Used to skip writing error messages yourself.
|
||||
\return true if the argument was found in the command.
|
||||
*/
|
||||
bool argget(const char* cmd, char* arg, int arg_num, bool optional)
|
||||
{
|
||||
if(strlen(cmd) >= deflen)
|
||||
return false;
|
||||
int argcount = arggetcount(cmd);
|
||||
if((arg_num + 1) > argcount)
|
||||
{
|
||||
if(!optional)
|
||||
dprintf("missing argument nr %d\n", arg_num + 1);
|
||||
return false;
|
||||
}
|
||||
int start = 0;
|
||||
while(cmd[start] != ' ') //ignore the command
|
||||
start++;
|
||||
while(cmd[start] == ' ') //ignore initial spaces
|
||||
start++;
|
||||
char temp_[deflen] = "";
|
||||
char* temp = temp_ + 1;
|
||||
strcpy_s(temp, deflen - 1, cmd + start);
|
||||
|
||||
int len = (int)strlen(temp);
|
||||
for(int i = 0; i < len; i++)
|
||||
if(temp[i] == '\\' and temp[i + 1] == '\\')
|
||||
{
|
||||
temp[i] = 1;
|
||||
temp[i + 1] = 1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
if(temp[i] == ',' and temp[i - 1] != '\\')
|
||||
temp[i] = 0;
|
||||
}
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
if(temp[i] == 1 and temp[i + 1] == 1)
|
||||
{
|
||||
temp[i] = '\\';
|
||||
temp[i + 1] = '\\';
|
||||
}
|
||||
|
||||
char new_temp[deflen] = "";
|
||||
int new_len = len;
|
||||
for(int i = 0, j = 0; i < len; i++) //handle escape characters
|
||||
{
|
||||
if(temp[i] == '\\' and (temp[i + 1] == ',' or temp[i + 1] == ' ' or temp[i + 1] == '\\'))
|
||||
{
|
||||
new_len--;
|
||||
j += sprintf(new_temp + j, "%c", temp[i + 1]);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
j += sprintf(new_temp + j, "%c", temp[i]);
|
||||
}
|
||||
len = new_len;
|
||||
memcpy(temp, new_temp, len + 1);
|
||||
if(arg_num == 0) //first argument
|
||||
{
|
||||
strcpy_s(arg, deflen, temp);
|
||||
return true;
|
||||
}
|
||||
for(int i = 0, j = 0; i < len; i++)
|
||||
{
|
||||
if(!temp[i])
|
||||
j++;
|
||||
if(j == arg_num)
|
||||
{
|
||||
strcpy_s(arg, deflen, temp + i + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef _ARGUMENT_H
|
||||
#define _ARGUMENT_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
//functions
|
||||
bool argget(const char* cmd, char* arg, int arg_num, bool optional);
|
||||
int arggetcount(const char* cmd);
|
||||
void argformat(char* cmd);
|
||||
|
||||
#endif
|
|
@ -5,11 +5,11 @@
|
|||
*/
|
||||
|
||||
#include "command.h"
|
||||
#include "argument.h"
|
||||
#include "value.h"
|
||||
#include "console.h"
|
||||
#include "debugger.h"
|
||||
#include "math.h"
|
||||
#include "commandparser.h"
|
||||
|
||||
/**
|
||||
\brief Finds a ::COMMAND in a command list.
|
||||
|
@ -205,7 +205,7 @@ CMDRESULT cmdloop(COMMAND* command_list, CBCOMMAND cbUnknownCommand, CBCOMMANDPR
|
|||
break;
|
||||
if(strlen(command))
|
||||
{
|
||||
argformat(command); //default formatting
|
||||
strcpy_s(command, StringUtils::Trim(command).c_str());
|
||||
COMMAND* cmd;
|
||||
if(!cbCommandFinder) //'clean' command processing
|
||||
cmd = cmdget(command_list, command);
|
||||
|
@ -230,14 +230,15 @@ CMDRESULT cmdloop(COMMAND* command_list, CBCOMMAND cbUnknownCommand, CBCOMMANDPR
|
|||
}
|
||||
else
|
||||
{
|
||||
int argcount = arggetcount(command);
|
||||
Command commandParsed(command);
|
||||
int argcount = commandParsed.GetArgCount();
|
||||
char** argv = (char**)emalloc((argcount + 1) * sizeof(char*), "cmdloop:argv");
|
||||
argv[0] = command;
|
||||
for(int i = 0; i < argcount; i++)
|
||||
{
|
||||
argv[i + 1] = (char*)emalloc(deflen, "cmdloop:argv[i+1]");
|
||||
*argv[i + 1] = 0;
|
||||
argget(command, argv[i + 1], i, true);
|
||||
strcpy_s(argv[i + 1], deflen, commandParsed.GetArg(i).c_str());
|
||||
}
|
||||
CMDRESULT res = cmd->cbCommand(argcount + 1, argv);
|
||||
for(int i = 0; i < argcount; i++)
|
||||
|
@ -365,21 +366,21 @@ CMDRESULT cmddirectexec(COMMAND* cmd_list, const char* cmd)
|
|||
if(!cmd or !strlen(cmd))
|
||||
return STATUS_ERROR;
|
||||
char command[deflen] = "";
|
||||
strcpy(command, cmd);
|
||||
argformat(command);
|
||||
strcpy(command, StringUtils::Trim(cmd).c_str());
|
||||
COMMAND* found = cmdfindmain(cmd_list, command);
|
||||
if(!found or !found->cbCommand)
|
||||
return STATUS_ERROR;
|
||||
if(found->debugonly and !DbgIsDebugging())
|
||||
return STATUS_ERROR;
|
||||
int argcount = arggetcount(command);
|
||||
Command cmdParsed(command);
|
||||
int argcount = cmdParsed.GetArgCount();
|
||||
char** argv = (char**)emalloc((argcount + 1) * sizeof(char*), "cmddirectexec:argv");
|
||||
argv[0] = command;
|
||||
for(int i = 0; i < argcount; i++)
|
||||
{
|
||||
argv[i + 1] = (char*)emalloc(deflen, "cmddirectexec:argv[i+1]");
|
||||
*argv[i + 1] = 0;
|
||||
argget(command, argv[i + 1], i, true);
|
||||
strcpy_s(argv[i + 1], deflen, cmdParsed.GetArg(i).c_str());
|
||||
}
|
||||
CMDRESULT res = found->cbCommand(argcount + 1, argv);
|
||||
for(int i = 0; i < argcount; i++)
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
#include "commandparser.h"
|
||||
|
||||
Command::Command(const String & command)
|
||||
{
|
||||
ParseState state = Default;
|
||||
int len = command.length();
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
char ch = command[i];
|
||||
switch(state)
|
||||
{
|
||||
case Default:
|
||||
switch(ch)
|
||||
{
|
||||
case ' ':
|
||||
if(!_tokens.size())
|
||||
dataFinish();
|
||||
break;
|
||||
case ',':
|
||||
dataFinish();
|
||||
break;
|
||||
case '\\':
|
||||
state = Escaped;
|
||||
break;
|
||||
case '\"':
|
||||
state = Text;
|
||||
break;
|
||||
default:
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Escaped:
|
||||
switch(ch)
|
||||
{
|
||||
case ' ':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
case ',':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
case '\"':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
default:
|
||||
dataAppend('\\');
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
state = Default;
|
||||
break;
|
||||
case Text:
|
||||
switch(ch)
|
||||
{
|
||||
case '\\':
|
||||
state = TextEscaped;
|
||||
break;
|
||||
case '\"':
|
||||
dataFinish();
|
||||
state = Default;
|
||||
break;
|
||||
default:
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TextEscaped:
|
||||
switch(ch)
|
||||
{
|
||||
case '\"':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
default:
|
||||
dataAppend('\\');
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
state = Text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(state == Escaped || state == TextEscaped)
|
||||
dataAppend('\\');
|
||||
dataFinish();
|
||||
}
|
||||
|
||||
const String Command::GetText()
|
||||
{
|
||||
return _tokens.size() ? _tokens[0] : String();
|
||||
}
|
||||
|
||||
const int Command::GetArgCount()
|
||||
{
|
||||
return _tokens.size() ? _tokens.size() - 1 : 0;
|
||||
}
|
||||
|
||||
const String Command::GetArg(int argnum)
|
||||
{
|
||||
return (int)_tokens.size() < argnum + 1 ? String() : _tokens[argnum + 1];
|
||||
}
|
||||
|
||||
void Command::dataAppend(const char ch)
|
||||
{
|
||||
_data += ch;
|
||||
}
|
||||
|
||||
void Command::dataFinish()
|
||||
{
|
||||
if(_data.length())
|
||||
{
|
||||
_tokens.push_back(_data);
|
||||
_data = "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef _COMMANDPARSER_H
|
||||
#define _COMMANDPARSER_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
Command(const String & command);
|
||||
const String GetText();
|
||||
const String GetArg(const int argnum);
|
||||
const int GetArgCount();
|
||||
|
||||
private:
|
||||
String _data;
|
||||
std::vector<String> _tokens;
|
||||
|
||||
enum ParseState
|
||||
{
|
||||
Default,
|
||||
Escaped,
|
||||
Text,
|
||||
TextEscaped
|
||||
};
|
||||
|
||||
void dataFinish();
|
||||
void dataAppend(const char ch);
|
||||
};
|
||||
|
||||
#endif // _COMMANDPARSER_H
|
|
@ -42,6 +42,7 @@ char sqlitedb[deflen] = "";
|
|||
PROCESS_INFORMATION* fdProcessInfo = &g_pi;
|
||||
HANDLE hActiveThread;
|
||||
bool bUndecorateSymbolNames = true;
|
||||
bool bEnableSourceDebugging = true;
|
||||
|
||||
static DWORD WINAPI memMapThread(void* ptr)
|
||||
{
|
||||
|
@ -188,9 +189,18 @@ DWORD WINAPI updateCallStackThread(void* ptr)
|
|||
|
||||
void DebugUpdateGui(uint disasm_addr, bool stack)
|
||||
{
|
||||
uint cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
if(MemIsValidReadPtr(disasm_addr))
|
||||
GuiDisasmAt(disasm_addr, cip);
|
||||
uint cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
if (MemIsValidReadPtr(disasm_addr))
|
||||
{
|
||||
if (bEnableSourceDebugging)
|
||||
{
|
||||
char szSourceFile[MAX_STRING_SIZE] = "";
|
||||
int line = 0;
|
||||
if (SymGetSourceLine(cip, szSourceFile, &line))
|
||||
GuiLoadSourceFile(szSourceFile, line);
|
||||
}
|
||||
GuiDisasmAt(disasm_addr, cip);
|
||||
}
|
||||
uint csp = GetContextDataEx(hActiveThread, UE_CSP);
|
||||
if(stack)
|
||||
GuiStackDumpAt(csp, csp);
|
||||
|
|
|
@ -131,5 +131,6 @@ extern HANDLE hActiveThread;
|
|||
extern char szFileName[MAX_PATH];
|
||||
extern char szSymbolCachePath[MAX_PATH];
|
||||
extern bool bUndecorateSymbolNames;
|
||||
extern bool bEnableSourceDebugging;
|
||||
|
||||
#endif // _DEBUGGER_H
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "memory.h"
|
||||
#include "threading.h"
|
||||
#include "variable.h"
|
||||
#include "argument.h"
|
||||
#include "plugin_loader.h"
|
||||
#include "simplescript.h"
|
||||
#include "symbolinfo.h"
|
||||
|
@ -35,8 +34,12 @@ CMDRESULT cbDebugInit(int argc, char* argv[])
|
|||
DbgCmdExecDirect("stop");
|
||||
|
||||
static char arg1[deflen] = "";
|
||||
if(!argget(*argv, arg1, 0, false))
|
||||
if(argc < 2)
|
||||
{
|
||||
dputs("not enough arguments!");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
strcpy_s(arg1, argv[1]);
|
||||
char szResolvedPath[MAX_PATH] = "";
|
||||
if(ResolveShortcut(GuiGetWindowHandle(), StringUtils::Utf8ToUtf16(arg1).c_str(), szResolvedPath, _countof(szResolvedPath)))
|
||||
{
|
||||
|
@ -76,13 +79,15 @@ CMDRESULT cbDebugInit(int argc, char* argv[])
|
|||
}
|
||||
|
||||
static char arg2[deflen] = "";
|
||||
argget(*argv, arg2, 1, true);
|
||||
if(argc > 2)
|
||||
strcpy_s(arg2, argv[2]);
|
||||
char* commandline = 0;
|
||||
if(strlen(arg2))
|
||||
commandline = arg2;
|
||||
|
||||
char arg3[deflen] = "";
|
||||
argget(*argv, arg3, 2, true);
|
||||
if(argc > 3)
|
||||
strcpy_s(arg3, argv[3]);
|
||||
|
||||
static char currentfolder[deflen] = "";
|
||||
strcpy_s(currentfolder, arg1);
|
||||
|
@ -140,25 +145,27 @@ CMDRESULT cbDebugErun(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugSetBPXOptions(int argc, char* argv[])
|
||||
{
|
||||
char argtype[deflen] = "";
|
||||
DWORD type = 0;
|
||||
if(!argget(*argv, argtype, 0, false))
|
||||
if(argc < 2)
|
||||
{
|
||||
dputs("not enough arguments!");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
DWORD type = 0;
|
||||
const char* a = 0;
|
||||
uint setting_type;
|
||||
if(strstr(argtype, "long"))
|
||||
if(strstr(argv[1], "long"))
|
||||
{
|
||||
setting_type = 1; //break_int3long
|
||||
a = "TYPE_LONG_INT3";
|
||||
type = UE_BREAKPOINT_LONG_INT3;
|
||||
}
|
||||
else if(strstr(argtype, "ud2"))
|
||||
else if(strstr(argv[1], "ud2"))
|
||||
{
|
||||
setting_type = 2; //break_ud2
|
||||
a = "TYPE_UD2";
|
||||
type = UE_BREAKPOINT_UD2;
|
||||
}
|
||||
else if(strstr(argtype, "short"))
|
||||
else if(strstr(argv[1], "short"))
|
||||
{
|
||||
setting_type = 0; //break_int3short
|
||||
a = "TYPE_INT3";
|
||||
|
@ -177,13 +184,20 @@ CMDRESULT cbDebugSetBPXOptions(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugSetBPX(int argc, char* argv[]) //bp addr [,name [,type]]
|
||||
{
|
||||
char argaddr[deflen] = "";
|
||||
if(!argget(*argv, argaddr, 0, false))
|
||||
if(argc < 2)
|
||||
{
|
||||
dputs("not enough arguments!");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
char argaddr[deflen] = "";
|
||||
strcpy_s(argaddr, argv[1]);
|
||||
char argname[deflen] = "";
|
||||
argget(*argv, argname, 1, true);
|
||||
if(argc > 2)
|
||||
strcpy_s(argname, argv[2]);
|
||||
char argtype[deflen] = "";
|
||||
bool has_arg2 = argget(*argv, argtype, 2, true);
|
||||
bool has_arg2 = argc > 3;
|
||||
if(has_arg2)
|
||||
strcpy_s(argtype, argv[3]);
|
||||
if(!has_arg2 and (scmp(argname, "ss") or scmp(argname, "long") or scmp(argname, "ud2")))
|
||||
{
|
||||
strcpy_s(argtype, argname);
|
||||
|
@ -247,8 +261,7 @@ CMDRESULT cbDebugSetBPX(int argc, char* argv[]) //bp addr [,name [,type]]
|
|||
|
||||
CMDRESULT cbDebugDeleteBPX(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
if(!argget(*argv, arg1, 0, true)) //delete all breakpoints
|
||||
if(argc < 2) //delete all breakpoints
|
||||
{
|
||||
if(!BpGetCount(BPNORMAL))
|
||||
{
|
||||
|
@ -262,7 +275,7 @@ CMDRESULT cbDebugDeleteBPX(int argc, char* argv[])
|
|||
return STATUS_CONTINUE;
|
||||
}
|
||||
BREAKPOINT found;
|
||||
if(BpGet(0, BPNORMAL, arg1, &found)) //found a breakpoint with name
|
||||
if(BpGet(0, BPNORMAL, argv[1], &found)) //found a breakpoint with name
|
||||
{
|
||||
if(!BpDelete(found.addr, BPNORMAL))
|
||||
{
|
||||
|
@ -278,9 +291,9 @@ CMDRESULT cbDebugDeleteBPX(int argc, char* argv[])
|
|||
return STATUS_CONTINUE;
|
||||
}
|
||||
uint addr = 0;
|
||||
if(!valfromstring(arg1, &addr) or !BpGet(addr, BPNORMAL, 0, &found)) //invalid breakpoint
|
||||
if(!valfromstring(argv[1], &addr) or !BpGet(addr, BPNORMAL, 0, &found)) //invalid breakpoint
|
||||
{
|
||||
dprintf("No such breakpoint \"%s\"\n", arg1);
|
||||
dprintf("No such breakpoint \"%s\"\n", argv[1]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(!BpDelete(found.addr, BPNORMAL))
|
||||
|
@ -301,8 +314,7 @@ CMDRESULT cbDebugDeleteBPX(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugEnableBPX(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
if(!argget(*argv, arg1, 0, true)) //enable all breakpoints
|
||||
if(argc < 2) //enable all breakpoints
|
||||
{
|
||||
if(!BpGetCount(BPNORMAL))
|
||||
{
|
||||
|
@ -316,7 +328,7 @@ CMDRESULT cbDebugEnableBPX(int argc, char* argv[])
|
|||
return STATUS_CONTINUE;
|
||||
}
|
||||
BREAKPOINT found;
|
||||
if(BpGet(0, BPNORMAL, arg1, &found)) //found a breakpoint with name
|
||||
if(BpGet(0, BPNORMAL, argv[1], &found)) //found a breakpoint with name
|
||||
{
|
||||
if(!BpEnable(found.addr, BPNORMAL, true) or !SetBPX(found.addr, found.titantype, (void*)cbUserBreakpoint))
|
||||
{
|
||||
|
@ -327,9 +339,9 @@ CMDRESULT cbDebugEnableBPX(int argc, char* argv[])
|
|||
return STATUS_CONTINUE;
|
||||
}
|
||||
uint addr = 0;
|
||||
if(!valfromstring(arg1, &addr) or !BpGet(addr, BPNORMAL, 0, &found)) //invalid breakpoint
|
||||
if(!valfromstring(argv[1], &addr) or !BpGet(addr, BPNORMAL, 0, &found)) //invalid breakpoint
|
||||
{
|
||||
dprintf("No such breakpoint \"%s\"\n", arg1);
|
||||
dprintf("No such breakpoint \"%s\"\n", argv[1]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(found.enabled)
|
||||
|
@ -350,8 +362,7 @@ CMDRESULT cbDebugEnableBPX(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugDisableBPX(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
if(!argget(*argv, arg1, 0, true)) //delete all breakpoints
|
||||
if(argc < 2) //delete all breakpoints
|
||||
{
|
||||
if(!BpGetCount(BPNORMAL))
|
||||
{
|
||||
|
@ -365,7 +376,7 @@ CMDRESULT cbDebugDisableBPX(int argc, char* argv[])
|
|||
return STATUS_CONTINUE;
|
||||
}
|
||||
BREAKPOINT found;
|
||||
if(BpGet(0, BPNORMAL, arg1, &found)) //found a breakpoint with name
|
||||
if(BpGet(0, BPNORMAL, argv[1], &found)) //found a breakpoint with name
|
||||
{
|
||||
if(!BpEnable(found.addr, BPNORMAL, false) or !DeleteBPX(found.addr))
|
||||
{
|
||||
|
@ -376,9 +387,9 @@ CMDRESULT cbDebugDisableBPX(int argc, char* argv[])
|
|||
return STATUS_CONTINUE;
|
||||
}
|
||||
uint addr = 0;
|
||||
if(!valfromstring(arg1, &addr) or !BpGet(addr, BPNORMAL, 0, &found)) //invalid breakpoint
|
||||
if(!valfromstring(argv[1], &addr) or !BpGet(addr, BPNORMAL, 0, &found)) //invalid breakpoint
|
||||
{
|
||||
dprintf("No such breakpoint \"%s\"\n", arg1);
|
||||
dprintf("No such breakpoint \"%s\"\n", argv[1]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(!found.enabled)
|
||||
|
@ -430,13 +441,10 @@ CMDRESULT cbDebugeStepOver(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugSingleStep(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
uint stepcount = 1;
|
||||
if(argget(*argv, arg1, 0, true))
|
||||
{
|
||||
if(!valfromstring(arg1, &stepcount))
|
||||
if(argc > 1)
|
||||
if(!valfromstring(argv[1], &stepcount))
|
||||
stepcount = 1;
|
||||
}
|
||||
SingleStep((DWORD)stepcount, (void*)cbStep);
|
||||
dbgsetstepping(true);
|
||||
return cbDebugRun(argc, argv);
|
||||
|
@ -459,10 +467,9 @@ CMDRESULT cbDebugHide(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugDisasm(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
uint addr = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
if(argget(*argv, arg1, 0, true))
|
||||
if(!valfromstring(arg1, &addr))
|
||||
uint addr;
|
||||
if(argc > 1)
|
||||
if(!valfromstring(argv[1], &addr))
|
||||
addr = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
if(!MemIsValidReadPtr(addr))
|
||||
return STATUS_CONTINUE;
|
||||
|
@ -472,24 +479,26 @@ CMDRESULT cbDebugDisasm(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugSetMemoryBpx(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = ""; //addr
|
||||
if(!argget(*argv, arg1, 0, false))
|
||||
if(argc < 2)
|
||||
{
|
||||
dputs("not enough arguments!");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
uint addr;
|
||||
if(!valfromstring(arg1, &addr))
|
||||
if(!valfromstring(argv[1], &addr))
|
||||
return STATUS_ERROR;
|
||||
bool restore = false;
|
||||
char arg2[deflen] = ""; //restore
|
||||
char arg3[deflen] = ""; //type
|
||||
argget(*argv, arg3, 2, true);
|
||||
if(argget(*argv, arg2, 1, true))
|
||||
char arg3[deflen] = "";
|
||||
if(argc > 3)
|
||||
strcpy_s(arg3, argv[3]);
|
||||
if(argc > 2)
|
||||
{
|
||||
if(*arg2 == '1')
|
||||
if(*argv[2] == '1')
|
||||
restore = true;
|
||||
else if(*arg2 == '0')
|
||||
else if(*argv[2] == '0')
|
||||
restore = false;
|
||||
else
|
||||
strcpy_s(arg3, arg2);
|
||||
strcpy_s(arg3, argv[2]);
|
||||
}
|
||||
DWORD type = UE_MEMORY;
|
||||
if(*arg3)
|
||||
|
@ -533,7 +542,7 @@ CMDRESULT cbDebugSetMemoryBpx(int argc, char* argv[])
|
|||
CMDRESULT cbDebugDeleteMemoryBreakpoint(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
if(!argget(*argv, arg1, 0, true)) //delete all breakpoints
|
||||
if(argc < 2) //delete all breakpoints
|
||||
{
|
||||
if(!BpGetCount(BPMEMORY))
|
||||
{
|
||||
|
@ -591,17 +600,18 @@ CMDRESULT cbDebugeRtr(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugSetHardwareBreakpoint(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = ""; //addr
|
||||
if(!argget(*argv, arg1, 0, false))
|
||||
if(argc < 2)
|
||||
{
|
||||
dputs("not enough arguments!");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
uint addr;
|
||||
if(!valfromstring(arg1, &addr))
|
||||
if(!valfromstring(argv[1], &addr))
|
||||
return STATUS_ERROR;
|
||||
DWORD type = UE_HARDWARE_EXECUTE;
|
||||
char arg2[deflen] = ""; //type
|
||||
if(argget(*argv, arg2, 1, true))
|
||||
if(argc > 2)
|
||||
{
|
||||
switch(*arg2)
|
||||
switch(*argv[2])
|
||||
{
|
||||
case 'r':
|
||||
type = UE_HARDWARE_READWRITE;
|
||||
|
@ -616,12 +626,11 @@ CMDRESULT cbDebugSetHardwareBreakpoint(int argc, char* argv[])
|
|||
break;
|
||||
}
|
||||
}
|
||||
char arg3[deflen] = ""; //size
|
||||
DWORD titsize = UE_HARDWARE_SIZE_1;
|
||||
if(argget(*argv, arg3, 2, true))
|
||||
if(argc > 3)
|
||||
{
|
||||
uint size;
|
||||
if(!valfromstring(arg3, &size))
|
||||
if(!valfromstring(argv[3], &size))
|
||||
return STATUS_ERROR;
|
||||
switch(size)
|
||||
{
|
||||
|
@ -683,8 +692,7 @@ CMDRESULT cbDebugSetHardwareBreakpoint(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugDeleteHardwareBreakpoint(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
if(!argget(*argv, arg1, 0, true)) //delete all breakpoints
|
||||
if(argc < 2) //delete all breakpoints
|
||||
{
|
||||
if(!BpGetCount(BPHARDWARE))
|
||||
{
|
||||
|
@ -698,7 +706,7 @@ CMDRESULT cbDebugDeleteHardwareBreakpoint(int argc, char* argv[])
|
|||
return STATUS_CONTINUE;
|
||||
}
|
||||
BREAKPOINT found;
|
||||
if(BpGet(0, BPHARDWARE, arg1, &found)) //found a breakpoint with name
|
||||
if(BpGet(0, BPHARDWARE, argv[1], &found)) //found a breakpoint with name
|
||||
{
|
||||
if(!BpDelete(found.addr, BPHARDWARE) or !DeleteHardwareBreakPoint(TITANGETDRX(found.titantype)))
|
||||
{
|
||||
|
@ -708,9 +716,9 @@ CMDRESULT cbDebugDeleteHardwareBreakpoint(int argc, char* argv[])
|
|||
return STATUS_CONTINUE;
|
||||
}
|
||||
uint addr = 0;
|
||||
if(!valfromstring(arg1, &addr) or !BpGet(addr, BPHARDWARE, 0, &found)) //invalid breakpoint
|
||||
if(!valfromstring(argv[1], &addr) or !BpGet(addr, BPHARDWARE, 0, &found)) //invalid breakpoint
|
||||
{
|
||||
dprintf("No such hardware breakpoint \"%s\"\n", arg1);
|
||||
dprintf("No such hardware breakpoint \"%s\"\n", argv[1]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(!BpDelete(found.addr, BPHARDWARE) or !DeleteHardwareBreakPoint(TITANGETDRX(found.titantype)))
|
||||
|
@ -725,10 +733,9 @@ CMDRESULT cbDebugDeleteHardwareBreakpoint(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugAlloc(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = ""; //size
|
||||
uint size = 0x1000;
|
||||
if(argget(*argv, arg1, 0, true))
|
||||
if(!valfromstring(arg1, &size, false))
|
||||
if(argc > 1)
|
||||
if(!valfromstring(argv[1], &size, false))
|
||||
return STATUS_ERROR;
|
||||
uint mem = (uint)MemAllocRemote(0, size, PAGE_EXECUTE_READWRITE);
|
||||
if(!mem)
|
||||
|
@ -748,11 +755,10 @@ CMDRESULT cbDebugFree(int argc, char* argv[])
|
|||
{
|
||||
uint lastalloc;
|
||||
varget("$lastalloc", &lastalloc, 0, 0);
|
||||
char arg1[deflen] = ""; //addr
|
||||
uint addr = lastalloc;
|
||||
if(argget(*argv, arg1, 0, true))
|
||||
if(argc > 1)
|
||||
{
|
||||
if(!valfromstring(arg1, &addr, false))
|
||||
if(!valfromstring(argv[1], &addr, false))
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
else if(!lastalloc)
|
||||
|
@ -774,7 +780,6 @@ CMDRESULT cbDebugFree(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugMemset(int argc, char* argv[])
|
||||
{
|
||||
char arg3[deflen] = ""; //size
|
||||
uint addr;
|
||||
uint value;
|
||||
uint size;
|
||||
|
@ -785,9 +790,9 @@ CMDRESULT cbDebugMemset(int argc, char* argv[])
|
|||
}
|
||||
if(!valfromstring(argv[1], &addr, false) or !valfromstring(argv[2], &value, false))
|
||||
return STATUS_ERROR;
|
||||
if(argget(*argv, arg3, 2, true))
|
||||
if(argc > 3)
|
||||
{
|
||||
if(!valfromstring(arg3, &size, false))
|
||||
if(!valfromstring(argv[3], &size, false))
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
else
|
||||
|
@ -1207,14 +1212,13 @@ CMDRESULT cbDebugSetPriority(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugEnableHardwareBreakpoint(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
DWORD drx = 0;
|
||||
if(!GetUnusedHardwareBreakPointRegister(&drx))
|
||||
{
|
||||
dputs("You can only set 4 hardware breakpoints");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(!argget(*argv, arg1, 0, true)) //enable all hardware breakpoints
|
||||
if(argc < 2) //enable all hardware breakpoints
|
||||
{
|
||||
if(!BpGetCount(BPHARDWARE))
|
||||
{
|
||||
|
@ -1229,9 +1233,9 @@ CMDRESULT cbDebugEnableHardwareBreakpoint(int argc, char* argv[])
|
|||
}
|
||||
BREAKPOINT found;
|
||||
uint addr = 0;
|
||||
if(!valfromstring(arg1, &addr) or !BpGet(addr, BPHARDWARE, 0, &found)) //invalid hardware breakpoint
|
||||
if(!valfromstring(argv[1], &addr) or !BpGet(addr, BPHARDWARE, 0, &found)) //invalid hardware breakpoint
|
||||
{
|
||||
dprintf("No such hardware breakpoint \"%s\"\n", arg1);
|
||||
dprintf("No such hardware breakpoint \"%s\"\n", argv[1]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(found.enabled)
|
||||
|
@ -1254,8 +1258,7 @@ CMDRESULT cbDebugEnableHardwareBreakpoint(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugDisableHardwareBreakpoint(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
if(!argget(*argv, arg1, 0, true)) //delete all hardware breakpoints
|
||||
if(argc < 2) //delete all hardware breakpoints
|
||||
{
|
||||
if(!BpGetCount(BPHARDWARE))
|
||||
{
|
||||
|
@ -1270,9 +1273,9 @@ CMDRESULT cbDebugDisableHardwareBreakpoint(int argc, char* argv[])
|
|||
}
|
||||
BREAKPOINT found;
|
||||
uint addr = 0;
|
||||
if(!valfromstring(arg1, &addr) or !BpGet(addr, BPHARDWARE, 0, &found)) //invalid hardware breakpoint
|
||||
if(!valfromstring(argv[1], &addr) or !BpGet(addr, BPHARDWARE, 0, &found)) //invalid hardware breakpoint
|
||||
{
|
||||
dprintf("No such hardware breakpoint \"%s\"\n", arg1);
|
||||
dprintf("No such hardware breakpoint \"%s\"\n", argv[1]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(!found.enabled)
|
||||
|
@ -1292,21 +1295,14 @@ CMDRESULT cbDebugDisableHardwareBreakpoint(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugEnableMemoryBreakpoint(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
DWORD drx = 0;
|
||||
if(!GetUnusedHardwareBreakPointRegister(0))
|
||||
{
|
||||
dputs("You can only set 4 hardware breakpoints");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(!argget(*argv, arg1, 0, true)) //enable all memory breakpoints
|
||||
if(argc < 2) //enable all memory breakpoints
|
||||
{
|
||||
if(!BpGetCount(BPMEMORY))
|
||||
{
|
||||
dputs("No hardware breakpoints to enable!");
|
||||
dputs("No memory breakpoints to enable!");
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
if(!BpEnumAll(cbEnableAllHardwareBreakpoints)) //at least one enable failed
|
||||
if(!BpEnumAll(cbEnableAllMemoryBreakpoints)) //at least one enable failed
|
||||
return STATUS_ERROR;
|
||||
dputs("All memory breakpoints enabled!");
|
||||
GuiUpdateAllViews();
|
||||
|
@ -1314,14 +1310,14 @@ CMDRESULT cbDebugEnableMemoryBreakpoint(int argc, char* argv[])
|
|||
}
|
||||
BREAKPOINT found;
|
||||
uint addr = 0;
|
||||
if(!valfromstring(arg1, &addr) or !BpGet(addr, BPMEMORY, 0, &found)) //invalid memory breakpoint
|
||||
if(!valfromstring(argv[1], &addr) or !BpGet(addr, BPMEMORY, 0, &found)) //invalid memory breakpoint
|
||||
{
|
||||
dprintf("No such memory breakpoint \"%s\"\n", arg1);
|
||||
dprintf("No such memory breakpoint \"%s\"\n", argv[1]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(found.enabled)
|
||||
{
|
||||
dputs("Hardware memory already enabled!");
|
||||
dputs("Memory memory already enabled!");
|
||||
GuiUpdateAllViews();
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
@ -1339,8 +1335,7 @@ CMDRESULT cbDebugEnableMemoryBreakpoint(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugDisableMemoryBreakpoint(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
if(!argget(*argv, arg1, 0, true)) //delete all memory breakpoints
|
||||
if(argc < 2) //delete all memory breakpoints
|
||||
{
|
||||
if(!BpGetCount(BPMEMORY))
|
||||
{
|
||||
|
@ -1355,9 +1350,9 @@ CMDRESULT cbDebugDisableMemoryBreakpoint(int argc, char* argv[])
|
|||
}
|
||||
BREAKPOINT found;
|
||||
uint addr = 0;
|
||||
if(!valfromstring(arg1, &addr) or !BpGet(addr, BPMEMORY, 0, &found)) //invalid memory breakpoint
|
||||
if(!valfromstring(argv[1], &addr) or !BpGet(addr, BPMEMORY, 0, &found)) //invalid memory breakpoint
|
||||
{
|
||||
dprintf("No such memory breakpoint \"%s\"\n", arg1);
|
||||
dprintf("No such memory breakpoint \"%s\"\n", argv[1]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(!found.enabled)
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
#include "instruction.h"
|
||||
#include "argument.h"
|
||||
#include "variable.h"
|
||||
#include "console.h"
|
||||
#include "value.h"
|
||||
|
@ -25,6 +24,7 @@
|
|||
#include "loop.h"
|
||||
#include "patternfind.h"
|
||||
#include "module.h"
|
||||
#include "stringformat.h"
|
||||
|
||||
static bool bRefinit = false;
|
||||
|
||||
|
@ -91,8 +91,9 @@ CMDRESULT cbInstrVar(int argc, char* argv[])
|
|||
dputs("not enough arguments!");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
char arg2[deflen] = "";
|
||||
argget(*argv, arg2, 1, true); //var value (optional)
|
||||
char arg2[deflen] = ""; //var value (optional)
|
||||
if(argc > 2)
|
||||
strcpy_s(arg2, argv[2]);
|
||||
uint value = 0;
|
||||
int add = 0;
|
||||
if(*argv[1] == '$')
|
||||
|
@ -219,15 +220,16 @@ CMDRESULT cbInstrMov(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbInstrVarList(int argc, char* argv[])
|
||||
{
|
||||
char arg1[deflen] = "";
|
||||
argget(*argv, arg1, 0, true);
|
||||
int filter = 0;
|
||||
if(!_stricmp(arg1, "USER"))
|
||||
filter = VAR_USER;
|
||||
else if(!_stricmp(arg1, "READONLY"))
|
||||
filter = VAR_READONLY;
|
||||
else if(!_stricmp(arg1, "SYSTEM"))
|
||||
filter = VAR_SYSTEM;
|
||||
if(argc > 1)
|
||||
{
|
||||
if(!_stricmp(argv[1], "USER"))
|
||||
filter = VAR_USER;
|
||||
else if(!_stricmp(argv[1], "READONLY"))
|
||||
filter = VAR_READONLY;
|
||||
else if(!_stricmp(argv[1], "SYSTEM"))
|
||||
filter = VAR_SYSTEM;
|
||||
}
|
||||
|
||||
size_t cbsize = 0;
|
||||
if(!varenum(0, &cbsize))
|
||||
|
@ -1777,3 +1779,19 @@ CMDRESULT cbInstrYaramod(int argc, char* argv[])
|
|||
sprintf_s(newcmd, "yara \"%s\",%p,%p", argv[1], base, size);
|
||||
return cmddirectexec(dbggetcommandlist(), newcmd);
|
||||
}
|
||||
|
||||
CMDRESULT cbInstrLog(int argc, char* argv[])
|
||||
{
|
||||
//log "format {0} string",arg1, arg2, argN
|
||||
if(argc == 1) //just log newline
|
||||
{
|
||||
dputs("");
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
FormatValueVector formatArgs;
|
||||
for(int i = 2; i < argc; i++)
|
||||
formatArgs.push_back(argv[i]);
|
||||
String logString = stringformat(argv[1], formatArgs);
|
||||
dputs(logString.c_str());
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
|
|
@ -64,5 +64,6 @@ CMDRESULT cbInstrSleep(int argc, char* argv[]);
|
|||
CMDRESULT cbInstrFindAsm(int argc, char* argv[]);
|
||||
CMDRESULT cbInstrYara(int argc, char* argv[]);
|
||||
CMDRESULT cbInstrYaramod(int argc, char* argv[]);
|
||||
CMDRESULT cbInstrLog(int argc, char* argv[]);
|
||||
|
||||
#endif // _INSTRUCTIONS_H
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
#include "simplescript.h"
|
||||
#include "value.h"
|
||||
#include "console.h"
|
||||
#include "argument.h"
|
||||
#include "variable.h"
|
||||
#include "threading.h"
|
||||
#include "x64_dbg.h"
|
||||
#include "debugger.h"
|
||||
#include "commandparser.h"
|
||||
|
||||
static std::vector<LINEMAPENTRY> linemap;
|
||||
|
||||
|
@ -28,8 +28,7 @@ static bool volatile bIsRunning = false;
|
|||
static SCRIPTBRANCHTYPE scriptgetbranchtype(const char* text)
|
||||
{
|
||||
char newtext[MAX_SCRIPT_LINE_SIZE] = "";
|
||||
strcpy_s(newtext, text);
|
||||
argformat(newtext); //format jump commands
|
||||
strcpy_s(newtext, StringUtils::Trim(text).c_str());
|
||||
if(!strstr(newtext, " "))
|
||||
strcat(newtext, " ");
|
||||
if(!strncmp(newtext, "jmp ", 4) or !strncmp(newtext, "goto ", 5))
|
||||
|
@ -187,7 +186,7 @@ static bool scriptcreatelinemap(const char* filename)
|
|||
{
|
||||
cur.type = linelabel;
|
||||
sprintf(cur.u.label, "l %.*s", rawlen - 1, cur.raw); //create a fake command for formatting
|
||||
argformat(cur.u.label); //format labels
|
||||
strcpy_s(cur.u.label, StringUtils::Trim(cur.u.label).c_str());
|
||||
char temp[256] = "";
|
||||
strcpy_s(temp, cur.u.label + 2);
|
||||
strcpy_s(cur.u.label, temp); //remove fake command
|
||||
|
@ -214,8 +213,7 @@ static bool scriptcreatelinemap(const char* filename)
|
|||
cur.type = linebranch;
|
||||
cur.u.branch.type = scriptgetbranchtype(cur.raw);
|
||||
char newraw[MAX_SCRIPT_LINE_SIZE] = "";
|
||||
strcpy_s(newraw, cur.raw);
|
||||
argformat(newraw);
|
||||
strcpy_s(newraw, StringUtils::Trim(cur.raw).c_str());
|
||||
int len = (int)strlen(newraw);
|
||||
for(int i = 0; i < len; i++)
|
||||
if(newraw[i] == ' ')
|
||||
|
@ -354,8 +352,7 @@ static CMDRESULT scriptinternalcmdexec(const char* cmd)
|
|||
else if(scriptisinternalcommand(cmd, "nop")) //do nothing
|
||||
return STATUS_CONTINUE;
|
||||
char command[deflen] = "";
|
||||
strcpy_s(command, cmd);
|
||||
argformat(command);
|
||||
strcpy_s(command, StringUtils::Trim(cmd).c_str());
|
||||
COMMAND* found = cmdfindmain(dbggetcommandlist(), command);
|
||||
if(!found) //invalid command
|
||||
return STATUS_ERROR;
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
#include "stringformat.h"
|
||||
#include "console.h"
|
||||
#include "value.h"
|
||||
#include "disasm_helper.h"
|
||||
|
||||
namespace ValueType
|
||||
{
|
||||
enum ValueType
|
||||
{
|
||||
Unknown,
|
||||
SignedDecimal,
|
||||
UnsignedDecimal,
|
||||
Hex,
|
||||
Pointer,
|
||||
String
|
||||
};
|
||||
}
|
||||
|
||||
static String printValue(FormatValueType value, ValueType::ValueType type)
|
||||
{
|
||||
uint valuint = 0;
|
||||
bool validval = valfromstring(value, &valuint);
|
||||
char result[deflen] = "???";
|
||||
switch(type)
|
||||
{
|
||||
case ValueType::Unknown:
|
||||
break;
|
||||
case ValueType::SignedDecimal:
|
||||
if(validval)
|
||||
sprintf_s(result, "%"fext"d", valuint);
|
||||
break;
|
||||
case ValueType::UnsignedDecimal:
|
||||
if(validval)
|
||||
sprintf_s(result, "%"fext"u", valuint);
|
||||
break;
|
||||
case ValueType::Hex:
|
||||
if(validval)
|
||||
sprintf_s(result, "%"fext"X", valuint);
|
||||
break;
|
||||
case ValueType::Pointer:
|
||||
if(validval)
|
||||
sprintf_s(result, "0x%"fhex, valuint);
|
||||
break;
|
||||
case ValueType::String:
|
||||
if(validval)
|
||||
{
|
||||
STRING_TYPE strtype;
|
||||
char string[512] = "";
|
||||
if(disasmgetstringat(valuint, &strtype, string, string, 500))
|
||||
strcpy_s(result, string);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static unsigned int getArgNumType(const String & formatString, ValueType::ValueType & type)
|
||||
{
|
||||
int add = 0;
|
||||
switch(formatString[0])
|
||||
{
|
||||
case 'd':
|
||||
type = ValueType::SignedDecimal;
|
||||
add++;
|
||||
break;
|
||||
case 'u':
|
||||
type = ValueType::UnsignedDecimal;
|
||||
add++;
|
||||
break;
|
||||
case 'p':
|
||||
type = ValueType::Pointer;
|
||||
add++;
|
||||
break;
|
||||
case 's':
|
||||
type = ValueType::String;
|
||||
add++;
|
||||
break;
|
||||
default:
|
||||
type = ValueType::Hex;
|
||||
}
|
||||
unsigned int argnum = 0;
|
||||
if(sscanf(formatString.c_str() + add, "%u", &argnum) != 1)
|
||||
type = ValueType::Unknown;
|
||||
return argnum;
|
||||
}
|
||||
|
||||
static String handleFormatString(const String & formatString, const FormatValueVector & values)
|
||||
{
|
||||
String result;
|
||||
ValueType::ValueType type = ValueType::Unknown;
|
||||
unsigned int argnum = getArgNumType(formatString, type);
|
||||
if(argnum < values.size())
|
||||
return printValue(values.at(argnum), type);
|
||||
return "[Formatting Error]";
|
||||
}
|
||||
|
||||
String stringformat(String format, const FormatValueVector & values)
|
||||
{
|
||||
StringUtils::ReplaceAll(format, "\\n", "\n");
|
||||
int len = (int)format.length();
|
||||
String output;
|
||||
String formatString;
|
||||
bool inFormatter = false;
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
//handle escaped format sequences "{{" and "}}"
|
||||
if(format[i] == '{' && (i + 1 < len && format[i + 1] == '{'))
|
||||
{
|
||||
output += "{";
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if(format[i] == '}' && (i + 1 < len && format[i + 1] == '}'))
|
||||
{
|
||||
output += "}";
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
//handle actual formatting
|
||||
if(format[i] == '{' && !inFormatter) //opening bracket
|
||||
{
|
||||
inFormatter = true;
|
||||
formatString.clear();
|
||||
}
|
||||
else if(format[i] == '}' && inFormatter) //closing bracket
|
||||
{
|
||||
inFormatter = false;
|
||||
if(formatString.length())
|
||||
{
|
||||
output += handleFormatString(formatString, values);
|
||||
formatString.clear();
|
||||
}
|
||||
}
|
||||
else if(inFormatter) //inside brackets
|
||||
formatString += format[i];
|
||||
else //outside brackets
|
||||
output += format[i];
|
||||
}
|
||||
if(inFormatter && formatString.size())
|
||||
output += handleFormatString(formatString, values);
|
||||
return output;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef _STRINGFORMAT_H
|
||||
#define _STRINGFORMAT_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
typedef const char* FormatValueType;
|
||||
typedef std::vector<FormatValueType> FormatValueVector;
|
||||
|
||||
String stringformat(String format, const FormatValueVector & values);
|
||||
|
||||
#endif //_STRINGFORMAT_H
|
|
@ -122,4 +122,25 @@ WString StringUtils::Utf8ToUtf16(const String & str)
|
|||
WString StringUtils::Utf8ToUtf16(const char* str)
|
||||
{
|
||||
return Utf8ToUtf16(str ? String(str) : String());
|
||||
}
|
||||
|
||||
//Taken from: http://stackoverflow.com/a/24315631
|
||||
void StringUtils::ReplaceAll(String & s, const String & from, const String & to)
|
||||
{
|
||||
size_t start_pos = 0;
|
||||
while((start_pos = s.find(from, start_pos)) != std::string::npos)
|
||||
{
|
||||
s.replace(start_pos, from.length(), to);
|
||||
start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
|
||||
}
|
||||
}
|
||||
|
||||
void StringUtils::ReplaceAll(WString & s, const WString & from, const WString & to)
|
||||
{
|
||||
size_t start_pos = 0;
|
||||
while((start_pos = s.find(from, start_pos)) != std::string::npos)
|
||||
{
|
||||
s.replace(start_pos, from.length(), to);
|
||||
start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
|
||||
}
|
||||
}
|
|
@ -22,6 +22,8 @@ public:
|
|||
static String Utf16ToUtf8(const wchar_t* wstr);
|
||||
static WString Utf8ToUtf16(const String & str);
|
||||
static WString Utf8ToUtf16(const char* str);
|
||||
static void ReplaceAll(String & s, const String & from, const String & to);
|
||||
static void ReplaceAll(WString & s, const WString & from, const WString & to);
|
||||
|
||||
private:
|
||||
static const String WHITESPACE;
|
||||
|
|
|
@ -248,3 +248,27 @@ const char* SymGetSymbolicName(uint Address)
|
|||
|
||||
return symbolicname;
|
||||
}
|
||||
|
||||
bool SymGetSourceLine(uint Cip, char* FileName, int* Line)
|
||||
{
|
||||
IMAGEHLP_LINE64 lineInfo;
|
||||
memset(&lineInfo, 0, sizeof(IMAGEHLP_LINE64));
|
||||
|
||||
lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
// Perform a symbol lookup from a specific address
|
||||
DWORD displacement;
|
||||
|
||||
if(!SafeSymGetLineFromAddr64(fdProcessInfo->hProcess, Cip, &displacement, &lineInfo))
|
||||
return false;
|
||||
|
||||
// Copy line number if requested
|
||||
if(Line)
|
||||
*Line = lineInfo.LineNumber;
|
||||
|
||||
// Copy file name if requested
|
||||
if(FileName)
|
||||
strcpy_s(FileName, MAX_STRING_SIZE, lineInfo.FileName);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -7,4 +7,13 @@ bool SymGetModuleList(std::vector<SYMBOLMODULEINFO>* List);
|
|||
void SymUpdateModuleList();
|
||||
void SymDownloadAllSymbols(const char* SymbolStore);
|
||||
bool SymAddrFromName(const char* Name, uint* Address);
|
||||
const char* SymGetSymbolicName(uint Address);
|
||||
const char* SymGetSymbolicName(uint Address);
|
||||
|
||||
/**
|
||||
\brief Gets the source code file name and line from an address.
|
||||
\param cip The address to check.
|
||||
\param [out] szFileName Source code file. Buffer of MAX_STRING_SIZE length. UTF-8. Can be null.
|
||||
\param [out] nLine Line number. Can be null.
|
||||
\return true if it succeeds, false if it fails.
|
||||
*/
|
||||
bool SymGetSourceLine(uint Cip, char* FileName, int* Line);
|
|
@ -36,14 +36,14 @@ void ThreadCreate(CREATE_THREAD_DEBUG_INFO* CreateThread)
|
|||
GuiUpdateThreadView();
|
||||
}
|
||||
|
||||
void ThreadExit(DWORD dwThreadId)
|
||||
void ThreadExit(DWORD ThreadId)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockThreads);
|
||||
|
||||
// Don't use a foreach loop here because of the erase() call
|
||||
for(auto itr = threadList.begin(); itr != threadList.end(); itr++)
|
||||
{
|
||||
if(itr->ThreadId == dwThreadId)
|
||||
if(itr->ThreadId == ThreadId)
|
||||
{
|
||||
threadList.erase(itr);
|
||||
break;
|
||||
|
@ -71,7 +71,7 @@ int ThreadGetCount()
|
|||
return (int)threadList.size();
|
||||
}
|
||||
|
||||
void ThreadGetList(THREADLIST* list)
|
||||
void ThreadGetList(THREADLIST* List)
|
||||
{
|
||||
SHARED_ACQUIRE(LockThreads);
|
||||
|
||||
|
@ -84,8 +84,8 @@ void ThreadGetList(THREADLIST* list)
|
|||
if(count <= 0)
|
||||
return;
|
||||
|
||||
list->count = (int)count;
|
||||
list->list = (THREADALLINFO*)BridgeAlloc(count * sizeof(THREADALLINFO));
|
||||
List->count = (int)count;
|
||||
List->list = (THREADALLINFO*)BridgeAlloc(count * sizeof(THREADALLINFO));
|
||||
|
||||
// Fill out the list data
|
||||
for(size_t i = 0; i < count; i++)
|
||||
|
@ -94,25 +94,25 @@ void ThreadGetList(THREADLIST* list)
|
|||
|
||||
// Get the debugger's current thread index
|
||||
if(threadHandle == hActiveThread)
|
||||
list->CurrentThread = (int)i;
|
||||
List->CurrentThread = (int)i;
|
||||
|
||||
memcpy(&list->list[i].BasicInfo, &threadList[i], sizeof(THREADINFO));
|
||||
memcpy(&List->list[i].BasicInfo, &threadList[i], sizeof(THREADINFO));
|
||||
|
||||
list->list[i].ThreadCip = GetContextDataEx(threadHandle, UE_CIP);
|
||||
list->list[i].SuspendCount = ThreadGetSuspendCount(threadHandle);
|
||||
list->list[i].Priority = ThreadGetPriority(threadHandle);
|
||||
list->list[i].WaitReason = ThreadGetWaitReason(threadHandle);
|
||||
list->list[i].LastError = ThreadGetLastError(list->list[i].BasicInfo.ThreadLocalBase);
|
||||
List->list[i].ThreadCip = GetContextDataEx(threadHandle, UE_CIP);
|
||||
List->list[i].SuspendCount = ThreadGetSuspendCount(threadHandle);
|
||||
List->list[i].Priority = ThreadGetPriority(threadHandle);
|
||||
List->list[i].WaitReason = ThreadGetWaitReason(threadHandle);
|
||||
List->list[i].LastError = ThreadGetLastError(List->list[i].BasicInfo.ThreadLocalBase);
|
||||
}
|
||||
}
|
||||
|
||||
bool ThreadIsValid(DWORD dwThreadId)
|
||||
bool ThreadIsValid(DWORD ThreadId)
|
||||
{
|
||||
SHARED_ACQUIRE(LockThreads);
|
||||
|
||||
for(auto & entry : threadList)
|
||||
{
|
||||
if(entry.ThreadId == dwThreadId)
|
||||
if(entry.ThreadId == ThreadId)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -159,31 +159,39 @@ THREADWAITREASON ThreadGetWaitReason(HANDLE Thread)
|
|||
return _Executive;
|
||||
}
|
||||
|
||||
DWORD ThreadGetLastError(uint tebAddress)
|
||||
DWORD ThreadGetLastError(DWORD ThreadId)
|
||||
{
|
||||
TEB teb;
|
||||
if(!ThreadGetTeb(tebAddress, &teb))
|
||||
{
|
||||
// TODO: Assert (Why would the TEB fail?)
|
||||
return 0;
|
||||
}
|
||||
SHARED_ACQUIRE(LockThreads);
|
||||
|
||||
TEB teb;
|
||||
for (auto & entry : threadList)
|
||||
{
|
||||
if (entry.ThreadId != ThreadId)
|
||||
continue;
|
||||
|
||||
if (!ThreadGetTeb(entry.ThreadLocalBase, &teb))
|
||||
{
|
||||
// TODO: Assert (Why would the TEB fail?)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return teb.LastErrorValue;
|
||||
}
|
||||
|
||||
bool ThreadSetName(DWORD dwThreadId, const char* name)
|
||||
bool ThreadSetName(DWORD ThreadId, const char* Name)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockThreads);
|
||||
|
||||
// Modifies a variable (name), so an exclusive lock is required
|
||||
for(auto & entry : threadList)
|
||||
{
|
||||
if(entry.ThreadId == dwThreadId)
|
||||
if(entry.ThreadId == ThreadId)
|
||||
{
|
||||
if(!name)
|
||||
name = "";
|
||||
if(!Name)
|
||||
Name = "";
|
||||
|
||||
strcpy_s(entry.threadName, name);
|
||||
strcpy_s(entry.threadName, Name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -191,13 +199,13 @@ bool ThreadSetName(DWORD dwThreadId, const char* name)
|
|||
return false;
|
||||
}
|
||||
|
||||
HANDLE ThreadGetHandle(DWORD dwThreadId)
|
||||
HANDLE ThreadGetHandle(DWORD ThreadId)
|
||||
{
|
||||
SHARED_ACQUIRE(LockThreads);
|
||||
|
||||
for(auto & entry : threadList)
|
||||
{
|
||||
if(entry.ThreadId == dwThreadId)
|
||||
if(entry.ThreadId == ThreadId)
|
||||
return entry.Handle;
|
||||
}
|
||||
|
||||
|
@ -206,20 +214,20 @@ HANDLE ThreadGetHandle(DWORD dwThreadId)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DWORD ThreadGetId(HANDLE hThread)
|
||||
DWORD ThreadGetId(HANDLE Thread)
|
||||
{
|
||||
SHARED_ACQUIRE(LockThreads);
|
||||
|
||||
// Search for the ID in the local list
|
||||
for(auto & entry : threadList)
|
||||
{
|
||||
if(entry.Handle == hThread)
|
||||
if(entry.Handle == Thread)
|
||||
return entry.ThreadId;
|
||||
}
|
||||
|
||||
// Wasn't found, check with Windows
|
||||
// NOTE: Requires VISTA+
|
||||
DWORD id = GetThreadId(hThread);
|
||||
DWORD id = GetThreadId(Thread);
|
||||
|
||||
// Returns 0 on error;
|
||||
// TODO: Same problem with ThreadGetHandle()
|
||||
|
|
|
@ -4,19 +4,19 @@
|
|||
#include "debugger.h"
|
||||
|
||||
void ThreadCreate(CREATE_THREAD_DEBUG_INFO* CreateThread);
|
||||
void ThreadExit(DWORD dwThreadId);
|
||||
void ThreadExit(DWORD ThreadId);
|
||||
void ThreadClear();
|
||||
int ThreadGetCount();
|
||||
void ThreadGetList(THREADLIST* list);
|
||||
bool ThreadIsValid(DWORD dwThreadId);
|
||||
bool ThreadSetName(DWORD dwTHreadId, const char* name);
|
||||
bool ThreadIsValid(DWORD ThreadId);
|
||||
bool ThreadSetName(DWORD ThreadId, const char* name);
|
||||
bool ThreadGetTeb(uint TEBAddress, TEB* Teb);
|
||||
int ThreadGetSuspendCount(HANDLE Thread);
|
||||
THREADPRIORITY ThreadGetPriority(HANDLE Thread);
|
||||
THREADWAITREASON ThreadGetWaitReason(HANDLE Thread);
|
||||
DWORD ThreadGetLastError(uint tebAddress);
|
||||
DWORD ThreadGetLastError(DWORD ThreadId);
|
||||
bool ThreadSetName(DWORD dwThreadId, const char* name);
|
||||
HANDLE ThreadGetHandle(DWORD dwThreadId);
|
||||
DWORD ThreadGetId(HANDLE hThread);
|
||||
HANDLE ThreadGetHandle(DWORD ThreadId);
|
||||
DWORD ThreadGetId(HANDLE Thread);
|
||||
int ThreadSuspendAll();
|
||||
int ThreadResumeAll();
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
#include "_global.h"
|
||||
#include "argument.h"
|
||||
#include "command.h"
|
||||
#include "variable.h"
|
||||
#include "instruction.h"
|
||||
|
@ -199,7 +198,8 @@ static void registercommands()
|
|||
dbgcmdnew("copystr\1strcpy", cbInstrCopystr, true); //write a string variable to memory
|
||||
dbgcmdnew("looplist", cbInstrLoopList, true); //list loops
|
||||
dbgcmdnew("yara", cbInstrYara, true); //yara test command
|
||||
dbgcmdnew("yaramod", cbInstrYaramod, true);
|
||||
dbgcmdnew("yaramod", cbInstrYaramod, true); //yara rule on module
|
||||
dbgcmdnew("log", cbInstrLog, false); //log command with superawesome hax
|
||||
}
|
||||
|
||||
static bool cbCommandProvider(char* cmd, int maxlen)
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="addrinfo.cpp" />
|
||||
<ClCompile Include="argument.cpp" />
|
||||
<ClCompile Include="assemble.cpp" />
|
||||
<ClCompile Include="bookmark.cpp" />
|
||||
<ClCompile Include="breakpoint.cpp" />
|
||||
<ClCompile Include="command.cpp" />
|
||||
<ClCompile Include="commandparser.cpp" />
|
||||
<ClCompile Include="comment.cpp" />
|
||||
<ClCompile Include="console.cpp" />
|
||||
<ClCompile Include="dbghelp_safe.cpp" />
|
||||
|
@ -50,6 +50,7 @@
|
|||
<ClCompile Include="reference.cpp" />
|
||||
<ClCompile Include="simplescript.cpp" />
|
||||
<ClCompile Include="stackinfo.cpp" />
|
||||
<ClCompile Include="stringformat.cpp" />
|
||||
<ClCompile Include="stringutils.cpp" />
|
||||
<ClCompile Include="symbolinfo.cpp" />
|
||||
<ClCompile Include="thread.cpp" />
|
||||
|
@ -64,7 +65,6 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="addrinfo.h" />
|
||||
<ClInclude Include="argument.h" />
|
||||
<ClInclude Include="assemble.h" />
|
||||
<ClInclude Include="BeaEngine\basic_types.h" />
|
||||
<ClInclude Include="BeaEngine\BeaEngine.h" />
|
||||
|
@ -73,6 +73,7 @@
|
|||
<ClInclude Include="bookmark.h" />
|
||||
<ClInclude Include="breakpoint.h" />
|
||||
<ClInclude Include="command.h" />
|
||||
<ClInclude Include="commandparser.h" />
|
||||
<ClInclude Include="comment.h" />
|
||||
<ClInclude Include="console.h" />
|
||||
<ClInclude Include="dbghelp\dbghelp.h" />
|
||||
|
@ -106,6 +107,7 @@
|
|||
<ClInclude Include="reference.h" />
|
||||
<ClInclude Include="simplescript.h" />
|
||||
<ClInclude Include="stackinfo.h" />
|
||||
<ClInclude Include="stringformat.h" />
|
||||
<ClInclude Include="stringutils.h" />
|
||||
<ClInclude Include="symbolinfo.h" />
|
||||
<ClInclude Include="thread.h" />
|
||||
|
|
|
@ -93,9 +93,6 @@
|
|||
<ClCompile Include="_global.cpp">
|
||||
<Filter>Source Files\Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="argument.cpp">
|
||||
<Filter>Source Files\Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="command.cpp">
|
||||
<Filter>Source Files\Core</Filter>
|
||||
</ClCompile>
|
||||
|
@ -201,6 +198,12 @@
|
|||
<ClCompile Include="dbghelp_safe.cpp">
|
||||
<Filter>Source Files\Utilities</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stringformat.cpp">
|
||||
<Filter>Source Files\Utilities</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="commandparser.cpp">
|
||||
<Filter>Source Files\Core</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="x64_dbg.h">
|
||||
|
@ -248,9 +251,6 @@
|
|||
<ClInclude Include="_global.h">
|
||||
<Filter>Header Files\Core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="argument.h">
|
||||
<Filter>Header Files\Core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="console.h">
|
||||
<Filter>Header Files\Core</Filter>
|
||||
</ClInclude>
|
||||
|
@ -467,5 +467,11 @@
|
|||
<ClInclude Include="yara\yara\utils.h">
|
||||
<Filter>Header Files\Third Party\yara\yara</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stringformat.h">
|
||||
<Filter>Header Files\Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="commandparser.h">
|
||||
<Filter>Header Files\Core</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -370,6 +370,11 @@ void Bridge::emitSymbolRefreshCurrent()
|
|||
emit symbolRefreshCurrent();
|
||||
}
|
||||
|
||||
void Bridge::emitLoadSourceFile(const QString path, int line)
|
||||
{
|
||||
emit loadSourceFile(path, line);
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Static Functions
|
||||
************************************************************************************/
|
||||
|
@ -828,6 +833,12 @@ void* Bridge::GuiDispatchMessage(GUIMSG type, void* param1, void* param2)
|
|||
}
|
||||
break;
|
||||
|
||||
case GUI_LOAD_SOURCE_FILE:
|
||||
{
|
||||
Bridge::getBridge()->emitLoadSourceFile(QString((const char*)param1), (int)param2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ public:
|
|||
void emitUpdatePatches();
|
||||
void emitUpdateCallStack();
|
||||
void emitSymbolRefreshCurrent();
|
||||
void emitLoadSourceFile(const QString path, int line = 0);
|
||||
|
||||
static DWORD WINAPI GuiDisptacherThread(LPVOID Argument);
|
||||
static void* GuiDispatchMessage(GUIMSG type, void* param1, void* param2);
|
||||
|
@ -151,6 +152,7 @@ signals:
|
|||
void updatePatches();
|
||||
void updateCallStack();
|
||||
void symbolRefreshCurrent();
|
||||
void loadSourceFile(const QString path, int line);
|
||||
|
||||
private:
|
||||
QMutex* mBridgeMutex;
|
||||
|
|
|
@ -125,10 +125,12 @@ void HexEditDialog::dataChangedSlot()
|
|||
|
||||
void HexEditDialog::on_lineEditAscii_textEdited(const QString & arg1)
|
||||
{
|
||||
Q_UNUSED(arg1);
|
||||
on_btnAscii2Hex_clicked();
|
||||
}
|
||||
|
||||
void HexEditDialog::on_lineEditUnicode_textEdited(const QString & arg1)
|
||||
{
|
||||
Q_UNUSED(arg1);
|
||||
on_btnUnicode2Hex_clicked();
|
||||
}
|
||||
|
|
|
@ -67,6 +67,12 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||
mSymbolView->setWindowIcon(QIcon(":/icons/images/pdb.png"));
|
||||
mSymbolView->hide();
|
||||
|
||||
// Source View
|
||||
mSourceViewManager = new SourceViewerManager();
|
||||
mSourceViewManager->setWindowTitle("Source");
|
||||
mSourceViewManager->setWindowIcon(QIcon(":/icons/images/source.png"));
|
||||
mSourceViewManager->hide();
|
||||
|
||||
// Breakpoints
|
||||
mBreakpointsView = new BreakpointsView();
|
||||
mBreakpointsView->setWindowTitle("Breakpoints");
|
||||
|
@ -122,6 +128,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||
mTabWidget->addTab(mCallStackView, mCallStackView->windowIcon(), mCallStackView->windowTitle());
|
||||
mTabWidget->addTab(mScriptView, mScriptView->windowIcon(), mScriptView->windowTitle());
|
||||
mTabWidget->addTab(mSymbolView, mSymbolView->windowIcon(), mSymbolView->windowTitle());
|
||||
mTabWidget->addTab(mSourceViewManager, mSourceViewManager->windowIcon(), mSourceViewManager->windowTitle());
|
||||
mTabWidget->addTab(mReferenceManager, mReferenceManager->windowIcon(), mReferenceManager->windowTitle());
|
||||
mTabWidget->addTab(mThreadView, mThreadView->windowIcon(), mThreadView->windowTitle());
|
||||
|
||||
|
@ -168,6 +175,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||
connect(ui->actionRunSelection, SIGNAL(triggered()), this, SLOT(runSelection()));
|
||||
connect(ui->actionCpu, SIGNAL(triggered()), this, SLOT(displayCpuWidget()));
|
||||
connect(ui->actionSymbolInfo, SIGNAL(triggered()), this, SLOT(displaySymbolWidget()));
|
||||
connect(ui->actionSource, SIGNAL(triggered()), this, SLOT(displaySourceViewWidget()));
|
||||
connect(mSymbolView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
|
||||
connect(mSymbolView, SIGNAL(showReferences()), this, SLOT(displayReferencesWidget()));
|
||||
connect(mReferenceManager, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
|
||||
|
@ -256,60 +264,65 @@ void MainWindow::setTab(QWidget* widget)
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::setGlobalShortcut(QAction* action, const QKeySequence & key)
|
||||
{
|
||||
action->setShortcut(key);
|
||||
action->setShortcutContext(Qt::ApplicationShortcut);
|
||||
}
|
||||
|
||||
void MainWindow::refreshShortcuts()
|
||||
{
|
||||
ui->actionOpen->setShortcut(ConfigShortcut("FileOpen"));
|
||||
ui->actionAttach->setShortcut(ConfigShortcut("FileAttach"));
|
||||
ui->actionDetach->setShortcut(ConfigShortcut("FileDetach"));
|
||||
ui->actionExit->setShortcut(ConfigShortcut("FileExit"));
|
||||
setGlobalShortcut(ui->actionOpen, ConfigShortcut("FileOpen"));
|
||||
setGlobalShortcut(ui->actionAttach, ConfigShortcut("FileAttach"));
|
||||
setGlobalShortcut(ui->actionDetach, ConfigShortcut("FileDetach"));
|
||||
setGlobalShortcut(ui->actionExit, ConfigShortcut("FileExit"));
|
||||
|
||||
ui->actionCpu->setShortcut(ConfigShortcut("ViewCpu"));
|
||||
ui->actionLog->setShortcut(ConfigShortcut("ViewLog"));
|
||||
ui->actionBreakpoints->setShortcut(ConfigShortcut("ViewBreakpoints"));
|
||||
ui->actionMemoryMap->setShortcut(ConfigShortcut("ViewMemoryMap"));
|
||||
ui->actionCallStack->setShortcut(ConfigShortcut("ViewCallStack"));
|
||||
ui->actionScript->setShortcut(ConfigShortcut("ViewScript"));
|
||||
ui->actionSymbolInfo->setShortcut(ConfigShortcut("ViewSymbolInfo"));
|
||||
ui->actionReferences->setShortcut(ConfigShortcut("ViewReferences"));
|
||||
ui->actionThreads->setShortcut(ConfigShortcut("ViewThreads"));
|
||||
ui->actionPatches->setShortcut(ConfigShortcut("ViewPatches"));
|
||||
ui->actionComments->setShortcut(ConfigShortcut("ViewComments"));
|
||||
ui->actionLabels->setShortcut(ConfigShortcut("ViewLabels"));
|
||||
ui->actionBookmarks->setShortcut(ConfigShortcut("ViewBookmarks"));
|
||||
ui->actionFunctions->setShortcut(ConfigShortcut("ViewFunctions"));
|
||||
setGlobalShortcut(ui->actionCpu, ConfigShortcut("ViewCpu"));
|
||||
setGlobalShortcut(ui->actionLog, ConfigShortcut("ViewLog"));
|
||||
setGlobalShortcut(ui->actionBreakpoints, ConfigShortcut("ViewBreakpoints"));
|
||||
setGlobalShortcut(ui->actionMemoryMap, ConfigShortcut("ViewMemoryMap"));
|
||||
setGlobalShortcut(ui->actionCallStack, ConfigShortcut("ViewCallStack"));
|
||||
setGlobalShortcut(ui->actionScript, ConfigShortcut("ViewScript"));
|
||||
setGlobalShortcut(ui->actionSymbolInfo, ConfigShortcut("ViewSymbolInfo"));
|
||||
setGlobalShortcut(ui->actionSource, ConfigShortcut("ViewSource"));
|
||||
setGlobalShortcut(ui->actionReferences, ConfigShortcut("ViewReferences"));
|
||||
setGlobalShortcut(ui->actionThreads, ConfigShortcut("ViewThreads"));
|
||||
setGlobalShortcut(ui->actionPatches, ConfigShortcut("ViewPatches"));
|
||||
setGlobalShortcut(ui->actionComments, ConfigShortcut("ViewComments"));
|
||||
setGlobalShortcut(ui->actionLabels, ConfigShortcut("ViewLabels"));
|
||||
setGlobalShortcut(ui->actionBookmarks, ConfigShortcut("ViewBookmarks"));
|
||||
setGlobalShortcut(ui->actionFunctions, ConfigShortcut("ViewFunctions"));
|
||||
|
||||
ui->actionRun->setShortcut(ConfigShortcut("DebugRun"));
|
||||
ui->actioneRun->setShortcut(ConfigShortcut("DebugeRun"));
|
||||
ui->actionRunSelection->setShortcut(ConfigShortcut("DebugRunSelection"));
|
||||
ui->actionPause->setShortcut(ConfigShortcut("DebugPause"));
|
||||
ui->actionRestart->setShortcut(ConfigShortcut("DebugRestart"));
|
||||
ui->actionClose->setShortcut(ConfigShortcut("DebugClose"));
|
||||
ui->actionStepInto->setShortcut(ConfigShortcut("DebugStepInto"));
|
||||
ui->actioneStepInto->setShortcut(ConfigShortcut("DebugeStepInfo"));
|
||||
ui->actionStepOver->setShortcut(ConfigShortcut("DebugStepOver"));
|
||||
ui->actioneStepOver->setShortcut(ConfigShortcut("DebugeStepOver"));
|
||||
ui->actionRtr->setShortcut(ConfigShortcut("DebugRtr"));
|
||||
ui->actioneRtr->setShortcut(ConfigShortcut("DebugeRtr"));
|
||||
ui->actionCommand->setShortcut(ConfigShortcut("DebugCommand"));
|
||||
ui->actionSkipNextInstruction->setShortcut(ConfigShortcut("DebugSkipNextInstruction"));
|
||||
setGlobalShortcut(ui->actionRun, ConfigShortcut("DebugRun"));
|
||||
setGlobalShortcut(ui->actioneRun, ConfigShortcut("DebugeRun"));
|
||||
setGlobalShortcut(ui->actionRunSelection, ConfigShortcut("DebugRunSelection"));
|
||||
setGlobalShortcut(ui->actionPause, ConfigShortcut("DebugPause"));
|
||||
setGlobalShortcut(ui->actionRestart, ConfigShortcut("DebugRestart"));
|
||||
setGlobalShortcut(ui->actionClose, ConfigShortcut("DebugClose"));
|
||||
setGlobalShortcut(ui->actionStepInto, ConfigShortcut("DebugStepInto"));
|
||||
setGlobalShortcut(ui->actioneStepInto, ConfigShortcut("DebugeStepInfo"));
|
||||
setGlobalShortcut(ui->actionStepOver, ConfigShortcut("DebugStepOver"));
|
||||
setGlobalShortcut(ui->actioneStepOver, ConfigShortcut("DebugeStepOver"));
|
||||
setGlobalShortcut(ui->actionRtr, ConfigShortcut("DebugRtr"));
|
||||
setGlobalShortcut(ui->actioneRtr, ConfigShortcut("DebugeRtr"));
|
||||
setGlobalShortcut(ui->actionCommand, ConfigShortcut("DebugCommand"));
|
||||
setGlobalShortcut(ui->actionSkipNextInstruction, ConfigShortcut("DebugSkipNextInstruction"));
|
||||
|
||||
ui->actionScylla->setShortcut(ConfigShortcut("PluginsScylla"));
|
||||
setGlobalShortcut(ui->actionScylla, ConfigShortcut("PluginsScylla"));
|
||||
|
||||
ui->actionSettings->setShortcut(ConfigShortcut("OptionsPreferences"));
|
||||
ui->actionAppearance->setShortcut(ConfigShortcut("OptionsAppearance"));
|
||||
ui->actionShortcuts->setShortcut(ConfigShortcut("OptionsShortcuts"));
|
||||
ui->actionTopmost->setShortcut(ConfigShortcut("OptionsTopmost"));
|
||||
|
||||
ui->actionAbout->setShortcut(ConfigShortcut("HelpAbout"));
|
||||
ui->actionDonate->setShortcut(ConfigShortcut("HelpDonate"));
|
||||
ui->actionCheckUpdates->setShortcut(ConfigShortcut("HelpCheckForUpdates"));
|
||||
ui->actionCalculator->setShortcut(ConfigShortcut("HelpCalculator"));
|
||||
ui->actionReportBug->setShortcut(ConfigShortcut("HelpReportBug"));
|
||||
|
||||
ui->actionStrings->setShortcut(ConfigShortcut("ActionFindStrings"));
|
||||
ui->actionCalls->setShortcut(ConfigShortcut("ActionFindIntermodularCalls"));
|
||||
setGlobalShortcut(ui->actionSettings, ConfigShortcut("OptionsPreferences"));
|
||||
setGlobalShortcut(ui->actionAppearance, ConfigShortcut("OptionsAppearance"));
|
||||
setGlobalShortcut(ui->actionShortcuts, ConfigShortcut("OptionsShortcuts"));
|
||||
setGlobalShortcut(ui->actionTopmost, ConfigShortcut("OptionsTopmost"));
|
||||
|
||||
setGlobalShortcut(ui->actionAbout, ConfigShortcut("HelpAbout"));
|
||||
setGlobalShortcut(ui->actionDonate, ConfigShortcut("HelpDonate"));
|
||||
setGlobalShortcut(ui->actionCheckUpdates, ConfigShortcut("HelpCheckForUpdates"));
|
||||
setGlobalShortcut(ui->actionCalculator, ConfigShortcut("HelpCalculator"));
|
||||
setGlobalShortcut(ui->actionReportBug, ConfigShortcut("HelpReportBug"));
|
||||
|
||||
setGlobalShortcut(ui->actionStrings, ConfigShortcut("ActionFindStrings"));
|
||||
setGlobalShortcut(ui->actionCalls, ConfigShortcut("ActionFindIntermodularCalls"));
|
||||
}
|
||||
|
||||
//Reads recent files list from settings
|
||||
|
@ -653,6 +666,13 @@ void MainWindow::displaySymbolWidget()
|
|||
setTab(mSymbolView);
|
||||
}
|
||||
|
||||
void MainWindow::displaySourceViewWidget()
|
||||
{
|
||||
mSourceViewManager->show();
|
||||
mSourceViewManager->setFocus();
|
||||
setTab(mSourceViewManager);
|
||||
}
|
||||
|
||||
void MainWindow::displayReferencesWidget()
|
||||
{
|
||||
mReferenceManager->show();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "CalculatorDialog.h"
|
||||
#include "StatusLabel.h"
|
||||
#include "UpdateChecker.h"
|
||||
#include "SourceViewerManager.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
|
@ -62,6 +63,7 @@ public slots:
|
|||
void execSkip();
|
||||
void displayCpuWidget();
|
||||
void displaySymbolWidget();
|
||||
void displaySourceViewWidget();
|
||||
void displayReferencesWidget();
|
||||
void displayThreadsWidget();
|
||||
void openSettings();
|
||||
|
@ -87,6 +89,7 @@ public slots:
|
|||
void displayFunctions();
|
||||
void checkUpdates();
|
||||
void displayCallstack();
|
||||
void setGlobalShortcut(QAction* action, const QKeySequence & key);
|
||||
void refreshShortcuts();
|
||||
void openShortcuts();
|
||||
void changeTopmost(bool checked);
|
||||
|
@ -106,6 +109,7 @@ private:
|
|||
CallStackView* mCallStackView;
|
||||
LogView* mLogView;
|
||||
SymbolView* mSymbolView;
|
||||
SourceViewerManager* mSourceViewManager;
|
||||
BreakpointsView* mBreakpointsView;
|
||||
ScriptView* mScriptView;
|
||||
ReferenceManager* mReferenceManager;
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
<addaction name="actionCallStack"/>
|
||||
<addaction name="actionScript"/>
|
||||
<addaction name="actionSymbolInfo"/>
|
||||
<addaction name="actionSource"/>
|
||||
<addaction name="actionReferences"/>
|
||||
<addaction name="actionThreads"/>
|
||||
<addaction name="actionPatches"/>
|
||||
|
@ -152,6 +153,7 @@
|
|||
<addaction name="actionCallStack"/>
|
||||
<addaction name="actionScript"/>
|
||||
<addaction name="actionSymbolInfo"/>
|
||||
<addaction name="actionSource"/>
|
||||
<addaction name="actionReferences"/>
|
||||
<addaction name="actionThreads"/>
|
||||
<addaction name="separator"/>
|
||||
|
@ -649,6 +651,18 @@
|
|||
<string>Report Bug</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSource">
|
||||
<property name="icon">
|
||||
<iconset resource="../../resource.qrc">
|
||||
<normaloff>:/icons/images/source.png</normaloff>:/icons/images/source.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Source</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Source</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
|
|
@ -121,6 +121,11 @@ void RegistersView::InitMappings()
|
|||
|
||||
offset++;
|
||||
|
||||
mRegisterMapping.insert(LastError, "LastError");
|
||||
mRegisterPlaces.insert(LastError, Register_Position(offset++, 0, 10, 20));
|
||||
|
||||
offset++;
|
||||
|
||||
mRegisterMapping.insert(GS, "GS");
|
||||
mRegisterPlaces.insert(GS, Register_Position(offset, 0, 3, 4));
|
||||
mRegisterMapping.insert(FS, "FS");
|
||||
|
@ -1025,6 +1030,8 @@ RegistersView::RegistersView(QWidget* parent) : QScrollArea(parent), mVScrollOff
|
|||
mFPU.insert(YMM15);
|
||||
#endif
|
||||
//registers that should not be changed
|
||||
mNoChange.insert(LastError);
|
||||
|
||||
mNoChange.insert(GS);
|
||||
mUSHORTDISPLAY.insert(GS);
|
||||
|
||||
|
@ -1452,6 +1459,15 @@ QString RegistersView::GetRegStringValueFromValue(REGISTER_NAME reg, char* value
|
|||
valueText += QString(")");
|
||||
}
|
||||
}
|
||||
else if(reg == LastError)
|
||||
{
|
||||
LASTERROR* data = (LASTERROR*)value;
|
||||
if(data->name)
|
||||
valueText = QString().sprintf("%08X (%s)", data->code, data->name);
|
||||
else
|
||||
valueText = QString().sprintf("%08X", data->code);
|
||||
mRegisterPlaces[LastError].valuesize = valueText.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
SIZE_T size = GetSizeRegister(reg);
|
||||
|
@ -1705,6 +1721,9 @@ void RegistersView::drawRegister(QPainter* p, REGISTER_NAME reg, char* value)
|
|||
else
|
||||
p->setPen(ConfigColor("RegistersColor"));
|
||||
|
||||
//get register value
|
||||
QString valueText = GetRegStringValueFromValue(reg, value);
|
||||
|
||||
//selection
|
||||
if(mSelected == reg)
|
||||
{
|
||||
|
@ -1712,9 +1731,7 @@ void RegistersView::drawRegister(QPainter* p, REGISTER_NAME reg, char* value)
|
|||
//p->fillRect(QRect(x + (mRegisterPlaces[reg].labelwidth)*mCharWidth ,mRowHeight*(mRegisterPlaces[reg].line)+2, mRegisterPlaces[reg].valuesize*mCharWidth, mRowHeight), QBrush(ConfigColor("RegistersSelectionColor")));
|
||||
}
|
||||
|
||||
QString valueText;
|
||||
// draw value
|
||||
valueText = GetRegStringValueFromValue(reg, value);
|
||||
width = mCharWidth * valueText.length();
|
||||
p->drawText(x, y, width, mRowHeight, Qt::AlignVCenter, valueText);
|
||||
//p->drawText(x + (mRegisterPlaces[reg].labelwidth)*mCharWidth ,mRowHeight*(mRegisterPlaces[reg].line+1),QString("%1").arg(value, mRegisterPlaces[reg].valuesize, 16, QChar('0')).toUpper());
|
||||
|
@ -2211,6 +2228,8 @@ SIZE_T RegistersView::GetSizeRegister(const REGISTER_NAME reg_name)
|
|||
size = 16;
|
||||
else if(mFPUYMM.contains(reg_name))
|
||||
size = 32;
|
||||
else if(reg_name == LastError)
|
||||
return sizeof(LASTERROR);
|
||||
else
|
||||
size = 0;
|
||||
|
||||
|
@ -2274,6 +2293,8 @@ char* RegistersView::registerValue(const REGDUMP* regd, const REGISTER_NAME reg)
|
|||
if(reg == CS) return (char*) & (regd->regcontext.cs);
|
||||
if(reg == SS) return (char*) & (regd->regcontext.ss);
|
||||
|
||||
if(reg == LastError) return (char*) & (regd->lastError);
|
||||
|
||||
if(reg == DR0) return (char*) & (regd->regcontext.dr0);
|
||||
if(reg == DR1) return (char*) & (regd->regcontext.dr1);
|
||||
if(reg == DR2) return (char*) & (regd->regcontext.dr2);
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
CIP,
|
||||
EFLAGS, CF, PF, AF, ZF, SF, TF, IF, DF, OF,
|
||||
GS, FS, ES, DS, CS, SS,
|
||||
LastError,
|
||||
DR0, DR1, DR2, DR3, DR6, DR7,
|
||||
// x87 stuff
|
||||
x87r0, x87r1, x87r2, x87r3, x87r4, x87r5, x87r6, x87r7,
|
||||
|
|
|
@ -55,6 +55,7 @@ void SettingsDialog::LoadSettings()
|
|||
settings.engineCalcType = calc_unsigned;
|
||||
settings.engineBreakpointType = break_int3short;
|
||||
settings.engineUndecorateSymbolNames = true;
|
||||
settings.engineEnableSourceDebugging = true;
|
||||
settings.exceptionRanges = &realExceptionRanges;
|
||||
settings.disasmArgumentSpaces = false;
|
||||
settings.disasmMemorySpaces = false;
|
||||
|
@ -110,6 +111,7 @@ void SettingsDialog::LoadSettings()
|
|||
}
|
||||
GetSettingBool("Engine", "UndecorateSymbolNames", &settings.engineUndecorateSymbolNames);
|
||||
GetSettingBool("Engine", "EnableDebugPrivilege", &settings.engineEnableDebugPrivilege);
|
||||
GetSettingBool("Engine", "EnableSourceDebugging", &settings.engineEnableSourceDebugging);
|
||||
switch(settings.engineCalcType)
|
||||
{
|
||||
case calc_signed:
|
||||
|
@ -133,6 +135,7 @@ void SettingsDialog::LoadSettings()
|
|||
}
|
||||
ui->chkUndecorateSymbolNames->setChecked(settings.engineUndecorateSymbolNames);
|
||||
ui->chkEnableDebugPrivilege->setChecked(settings.engineEnableDebugPrivilege);
|
||||
ui->chkEnableSourceDebugging->setChecked(settings.engineEnableSourceDebugging);
|
||||
|
||||
//Exceptions tab
|
||||
char exceptionRange[MAX_SETTING_SIZE] = "";
|
||||
|
@ -229,6 +232,7 @@ void SettingsDialog::SaveSettings()
|
|||
BridgeSettingSetUint("Engine", "BreakpointType", settings.engineBreakpointType);
|
||||
BridgeSettingSetUint("Engine", "UndecorateSymbolNames", settings.engineUndecorateSymbolNames);
|
||||
BridgeSettingSetUint("Engine", "EnableDebugPrivilege", settings.engineEnableDebugPrivilege);
|
||||
BridgeSettingSetUint("Engine", "EnableSourceDebugging", settings.engineEnableSourceDebugging);
|
||||
|
||||
//Exceptions tab
|
||||
QString exceptionRange = "";
|
||||
|
@ -485,12 +489,17 @@ void SettingsDialog::on_chkUndecorateSymbolNames_stateChanged(int arg1)
|
|||
|
||||
void SettingsDialog::on_chkEnableDebugPrivilege_stateChanged(int arg1)
|
||||
{
|
||||
if(arg1 == Qt::Unchecked)
|
||||
if(arg1 == Qt::Unchecked) //wtf stupid shit
|
||||
settings.engineEnableDebugPrivilege = false;
|
||||
else
|
||||
settings.engineEnableDebugPrivilege = true;
|
||||
}
|
||||
|
||||
void SettingsDialog::on_chkEnableSourceDebugging_stateChanged(int arg1)
|
||||
{
|
||||
settings.engineEnableSourceDebugging = arg1 == Qt::Checked;
|
||||
}
|
||||
|
||||
void SettingsDialog::on_btnAddRange_clicked()
|
||||
{
|
||||
ExceptionRangeDialog exceptionRange(this);
|
||||
|
|
|
@ -43,6 +43,7 @@ private slots:
|
|||
void on_radioUd2_clicked();
|
||||
void on_chkUndecorateSymbolNames_stateChanged(int arg1);
|
||||
void on_chkEnableDebugPrivilege_stateChanged(int arg1);
|
||||
void on_chkEnableSourceDebugging_stateChanged(int arg1);
|
||||
//Exception tab
|
||||
void on_btnAddRange_clicked();
|
||||
void on_btnDeleteRange_clicked();
|
||||
|
@ -56,7 +57,6 @@ private slots:
|
|||
void on_chkSetJIT_stateChanged(int arg1);
|
||||
void on_chkConfirmBeforeAtt_stateChanged(int arg1);
|
||||
|
||||
|
||||
private:
|
||||
//enums
|
||||
enum CalcType
|
||||
|
@ -106,6 +106,7 @@ private:
|
|||
BreakpointType engineBreakpointType;
|
||||
bool engineUndecorateSymbolNames;
|
||||
bool engineEnableDebugPrivilege;
|
||||
bool engineEnableSourceDebugging;
|
||||
//Exception Tab
|
||||
QList<RangeStruct>* exceptionRanges;
|
||||
//Disasm Tab
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>308</width>
|
||||
<height>220</height>
|
||||
<width>350</width>
|
||||
<height>250</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -245,6 +245,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="chkEnableSourceDebugging">
|
||||
<property name="text">
|
||||
<string>Enable Source Debugging</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
#include "SourceView.h"
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QMessageBox>
|
||||
#include "Configuration.h"
|
||||
|
||||
SourceView::SourceView(QString path, int line, StdTable* parent) : StdTable(parent)
|
||||
{
|
||||
mSourcePath = path;
|
||||
|
||||
addColumnAt(8 + 4 * getCharWidth(), "Line", true);
|
||||
addColumnAt(0, "Code", true);
|
||||
|
||||
loadFile();
|
||||
setInstructionPointer(line);
|
||||
}
|
||||
|
||||
void SourceView::setInstructionPointer(int line)
|
||||
{
|
||||
int offset = line - 1;
|
||||
if(!isValidIndex(offset, 0))
|
||||
{
|
||||
mIpLine = 0;
|
||||
return;
|
||||
}
|
||||
mIpLine = line;
|
||||
int rangefrom = getTableOffset();
|
||||
int rangeto = rangefrom + getViewableRowsCount() - 1;
|
||||
if(offset < rangefrom) //ip lays before the current view
|
||||
setTableOffset(offset);
|
||||
else if(offset > (rangeto - 1)) //ip lays after the current view
|
||||
setTableOffset(offset - getViewableRowsCount() + 2);
|
||||
setSingleSelection(offset);
|
||||
reloadData(); //repaint
|
||||
}
|
||||
|
||||
QString SourceView::getSourcePath()
|
||||
{
|
||||
return mSourcePath;
|
||||
}
|
||||
|
||||
void SourceView::loadFile()
|
||||
{
|
||||
QFile file(mSourcePath);
|
||||
if(!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
return; //error?
|
||||
}
|
||||
QTextStream in(&file);
|
||||
int lineNum = 0;
|
||||
while(!in.atEnd())
|
||||
{
|
||||
QString line = in.readLine().replace('\t', " "); //replace tabs with four spaces
|
||||
setRowCount(lineNum + 1);
|
||||
setCellContent(lineNum, 0, QString().sprintf("%04d", lineNum + 1));
|
||||
setCellContent(lineNum, 1, line);
|
||||
lineNum++;
|
||||
}
|
||||
reloadData();
|
||||
file.close();
|
||||
}
|
||||
|
||||
QString SourceView::paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h)
|
||||
{
|
||||
painter->save();
|
||||
bool wIsSelected = isSelected(rowBase, rowOffset);
|
||||
// Highlight if selected
|
||||
if(wIsSelected)
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(selectionColor)); //ScriptViewSelectionColor
|
||||
QString returnString;
|
||||
int line = rowBase + rowOffset + 1;
|
||||
switch(col)
|
||||
{
|
||||
case 0: //line number
|
||||
{
|
||||
if(line == mIpLine) //IP
|
||||
{
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(ConfigColor("DisassemblyCipBackgroundColor")));
|
||||
painter->setPen(QPen(ConfigColor("DisassemblyCipColor"))); //white address (ScriptViewIpTextColor)
|
||||
}
|
||||
else
|
||||
painter->setPen(QPen(this->textColor));
|
||||
painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, QString().sprintf("%04d", line));
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: //command
|
||||
{
|
||||
returnString = getCellContent(rowBase + rowOffset, col); //TODO: simple keyword/regex-based syntax highlighting
|
||||
}
|
||||
break;
|
||||
}
|
||||
painter->restore();
|
||||
return returnString;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef SOURCEVIEW_H
|
||||
#define SOURCEVIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "StdTable.h"
|
||||
|
||||
class SourceView : public StdTable
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SourceView(QString path, int line = 0, StdTable* parent = 0);
|
||||
QString getSourcePath();
|
||||
void setInstructionPointer(int line);
|
||||
QString paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h);
|
||||
|
||||
private:
|
||||
QString mSourcePath;
|
||||
int mIpLine;
|
||||
void loadFile();
|
||||
};
|
||||
|
||||
#endif // SOURCEVIEW_H
|
|
@ -0,0 +1,58 @@
|
|||
#include "SourceViewerManager.h"
|
||||
#include "Bridge.h"
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
||||
SourceViewerManager::SourceViewerManager(QWidget* parent) : QTabWidget(parent)
|
||||
{
|
||||
setMovable(true);
|
||||
setTabsClosable(true);
|
||||
|
||||
//Close All Tabs
|
||||
mCloseAllTabs = new QPushButton(this);
|
||||
mCloseAllTabs->setIcon(QIcon(":/icons/images/close-all-tabs.png"));
|
||||
mCloseAllTabs->setToolTip("Close All Tabs");
|
||||
connect(mCloseAllTabs, SIGNAL(clicked()), this, SLOT(closeAllTabs()));
|
||||
setCornerWidget(mCloseAllTabs, Qt::TopLeftCorner);
|
||||
|
||||
connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
|
||||
connect(Bridge::getBridge(), SIGNAL(loadSourceFile(QString, int)), this, SLOT(loadSourceFile(QString, int)));
|
||||
}
|
||||
|
||||
void SourceViewerManager::loadSourceFile(QString path, int line)
|
||||
{
|
||||
for(int i = 0; i < count(); i++) //remove all other instruction pointers (only one is possible)
|
||||
((SourceView*)this->widget(i))->setInstructionPointer(0);
|
||||
for(int i = 0; i < count(); i++)
|
||||
{
|
||||
SourceView* curView = (SourceView*)this->widget(i);
|
||||
if(curView->getSourcePath().compare(path, Qt::CaseInsensitive) == 0) //file already loaded
|
||||
{
|
||||
curView->setInstructionPointer(line);
|
||||
setCurrentIndex(i); //show that loaded tab
|
||||
return;
|
||||
}
|
||||
}
|
||||
//check if file actually exists
|
||||
if(!QFileInfo(path).exists())
|
||||
{
|
||||
return; //error?
|
||||
}
|
||||
//load the new file
|
||||
QString title = path;
|
||||
int idx = path.lastIndexOf(QDir::separator());
|
||||
if(idx != -1)
|
||||
title = path.mid(idx + 1);
|
||||
addTab(new SourceView(path, line), title);
|
||||
setCurrentIndex(count() - 1);
|
||||
}
|
||||
|
||||
void SourceViewerManager::closeTab(int index)
|
||||
{
|
||||
removeTab(index);
|
||||
}
|
||||
|
||||
void SourceViewerManager::closeAllTabs()
|
||||
{
|
||||
clear();
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef SOURCEVIEWERMANAGER_H
|
||||
#define SOURCEVIEWERMANAGER_H
|
||||
|
||||
#include <QTabWidget>
|
||||
#include <QPushButton>
|
||||
#include <QMap>
|
||||
#include "SourceView.h"
|
||||
|
||||
class SourceViewerManager : public QTabWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SourceViewerManager(QWidget* parent = 0);
|
||||
|
||||
public slots:
|
||||
void loadSourceFile(QString path, int line);
|
||||
void closeTab(int index);
|
||||
void closeAllTabs();
|
||||
|
||||
private:
|
||||
QPushButton* mCloseAllTabs;
|
||||
};
|
||||
|
||||
#endif // SOURCEVIEWERMANAGER_H
|
|
@ -52,6 +52,11 @@ void StatusLabel::logUpdate(QString message)
|
|||
if(labelText.contains(QChar('\n'))) //newline
|
||||
labelText = "";
|
||||
labelText += message;
|
||||
setText(labelText);
|
||||
//only show the last line in the status label
|
||||
QStringList lineList = labelText.split(QChar('\n'), QString::SkipEmptyParts);
|
||||
if(lineList.size())
|
||||
setText(lineList[lineList.length() - 1]);
|
||||
else
|
||||
setText(labelText);
|
||||
this->repaint();
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@ void YaraRuleSelectionDialog::on_buttonFile_clicked()
|
|||
|
||||
void YaraRuleSelectionDialog::on_buttonSelect_clicked()
|
||||
{
|
||||
if(!ui->listRules->selectedItems().size()) //no selection
|
||||
return;
|
||||
int selectedIndex = ui->listRules->row(ui->listRules->selectedItems().at(0));
|
||||
selectedFile = ruleFiles.at(selectedIndex).first;
|
||||
this->accept();
|
||||
|
|
|
@ -187,6 +187,7 @@ Configuration::Configuration() : QObject()
|
|||
defaultShortcuts.insert("ViewCallStack", Shortcut(tr("View -> Call Stack"), "Alt+K", true));
|
||||
defaultShortcuts.insert("ViewScript", Shortcut(tr("View -> Script"), "Alt+S", true));
|
||||
defaultShortcuts.insert("ViewSymbolInfo", Shortcut(tr("View -> Symbol Info"), "Ctrl+Alt+S", true));
|
||||
defaultShortcuts.insert("ViewSource", Shortcut(tr("View -> Source"), "Ctrl+Shift+S", true));
|
||||
defaultShortcuts.insert("ViewReferences", Shortcut(tr("View -> References"), "Alt+R", true));
|
||||
defaultShortcuts.insert("ViewThreads", Shortcut(tr("View -> Threads"), "Alt+T", true));
|
||||
defaultShortcuts.insert("ViewPatches", Shortcut(tr("View -> Patches"), "Ctrl+P", true));
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 308 B |
|
@ -53,5 +53,6 @@
|
|||
<file>images/bug-report.png</file>
|
||||
<file>images/yara.png</file>
|
||||
<file>images/data-copy.png</file>
|
||||
<file>images/source.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -88,7 +88,9 @@ SOURCES += \
|
|||
Src/Gui/ReferenceManager.cpp \
|
||||
Src/Bridge/BridgeResult.cpp \
|
||||
Src/Gui/YaraRuleSelectionDialog.cpp \
|
||||
Src/Gui/DataCopyDialog.cpp
|
||||
Src/Gui/DataCopyDialog.cpp \
|
||||
Src/Gui/SourceViewerManager.cpp \
|
||||
Src/Gui/SourceView.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
|
@ -155,7 +157,9 @@ HEADERS += \
|
|||
Src/Gui/ReferenceManager.h \
|
||||
Src/Bridge/BridgeResult.h \
|
||||
Src/Gui/YaraRuleSelectionDialog.h \
|
||||
Src/Gui/DataCopyDialog.h
|
||||
Src/Gui/DataCopyDialog.h \
|
||||
Src/Gui/SourceViewerManager.h \
|
||||
Src/Gui/SourceView.h
|
||||
|
||||
|
||||
INCLUDEPATH += \
|
||||
|
|
Loading…
Reference in New Issue