Added more debug dumping for gsc vm

This commit is contained in:
ineed bots 2023-09-05 23:57:03 -06:00
parent bd128a1366
commit 6b3996416a
4 changed files with 260 additions and 6 deletions

View File

@ -61,7 +61,7 @@ std::string printStack()
unsigned short frames;
SYMBOL_INFO * symbol;
HANDLE process;
std::string answer;
std::string answer{};
process = GetCurrentProcess();
@ -76,7 +76,7 @@ std::string printStack()
{
SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );
answer += std::format("{}: {} - {:06x}\n", frames - i - 1, symbol->Name, symbol->Address);
answer += std::format("{}: {} - 0x{:06x}\n", frames - i - 1, symbol->Name, symbol->Address);
}
free( symbol );
@ -84,17 +84,257 @@ std::string printStack()
return answer;
}
int op_idx[game::SCRIPT_INSTANCE_MAX] = { 0, 0 };
bool op_idx_rolled_over[game::SCRIPT_INSTANCE_MAX] = { false, false };
game::OpcodeVM op_history[game::SCRIPT_INSTANCE_MAX][128] = {};
std::string build_op_history(game::scriptInstance_t inst)
{
static const char* OpcodeVMToString[] = {
"OP_End",
"OP_Return",
"OP_GetUndefined",
"OP_GetZero",
"OP_GetByte",
"OP_GetNegByte",
"OP_GetUnsignedShort",
"OP_GetNegUnsignedShort",
"OP_GetInteger",
"OP_GetFloat",
"OP_GetString",
"OP_GetIString",
"OP_GetVector",
"OP_GetLevelObject",
"OP_GetAnimObject",
"OP_GetSelf",
"OP_GetLevel",
"OP_GetGame",
"OP_GetAnim",
"OP_GetAnimation",
"OP_GetGameRef",
"OP_GetFunction",
"OP_CreateLocalVariable",
"OP_RemoveLocalVariables",
"OP_EvalLocalVariableCached0",
"OP_EvalLocalVariableCached1",
"OP_EvalLocalVariableCached2",
"OP_EvalLocalVariableCached3",
"OP_EvalLocalVariableCached4",
"OP_EvalLocalVariableCached5",
"OP_EvalLocalVariableCached",
"OP_EvalLocalArrayCached",
"OP_EvalArray",
"OP_EvalLocalArrayRefCached0",
"OP_EvalLocalArrayRefCached",
"OP_EvalArrayRef",
"OP_ClearArray",
"OP_EmptyArray",
"OP_GetSelfObject",
"OP_EvalLevelFieldVariable",
"OP_EvalAnimFieldVariable",
"OP_EvalSelfFieldVariable",
"OP_EvalFieldVariable",
"OP_EvalLevelFieldVariableRef",
"OP_EvalAnimFieldVariableRef",
"OP_EvalSelfFieldVariableRef",
"OP_EvalFieldVariableRef",
"OP_ClearFieldVariable",
"OP_SafeCreateVariableFieldCached",
"OP_SafeSetVariableFieldCached0",
"OP_SafeSetVariableFieldCached",
"OP_SafeSetWaittillVariableFieldCached",
"OP_clearparams",
"OP_checkclearparams",
"OP_EvalLocalVariableRefCached0",
"OP_EvalLocalVariableRefCached",
"OP_SetLevelFieldVariableField",
"OP_SetVariableField",
"OP_SetAnimFieldVariableField",
"OP_SetSelfFieldVariableField",
"OP_SetLocalVariableFieldCached0",
"OP_SetLocalVariableFieldCached",
"OP_CallBuiltin0",
"OP_CallBuiltin1",
"OP_CallBuiltin2",
"OP_CallBuiltin3",
"OP_CallBuiltin4",
"OP_CallBuiltin5",
"OP_CallBuiltin",
"OP_CallBuiltinMethod0",
"OP_CallBuiltinMethod1",
"OP_CallBuiltinMethod2",
"OP_CallBuiltinMethod3",
"OP_CallBuiltinMethod4",
"OP_CallBuiltinMethod5",
"OP_CallBuiltinMethod",
"OP_wait",
"OP_waittillFrameEnd",
"OP_PreScriptCall",
"OP_ScriptFunctionCall2",
"OP_ScriptFunctionCall",
"OP_ScriptFunctionCallPointer",
"OP_ScriptMethodCall",
"OP_ScriptMethodCallPointer",
"OP_ScriptThreadCall",
"OP_ScriptThreadCallPointer",
"OP_ScriptMethodThreadCall",
"OP_ScriptMethodThreadCallPointer",
"OP_DecTop",
"OP_CastFieldObject",
"OP_EvalLocalVariableObjectCached",
"OP_CastBool",
"OP_BoolNot",
"OP_BoolComplement",
"OP_JumpOnFalse",
"OP_JumpOnTrue",
"OP_JumpOnFalseExpr",
"OP_JumpOnTrueExpr",
"OP_jump",
"OP_jumpback",
"OP_inc",
"OP_dec",
"OP_bit_or",
"OP_bit_ex_or",
"OP_bit_and",
"OP_equality",
"OP_inequality",
"OP_less",
"OP_greater",
"OP_less_equal",
"OP_greater_equal",
"OP_shift_left",
"OP_shift_right",
"OP_plus",
"OP_minus",
"OP_multiply",
"OP_divide",
"OP_mod",
"OP_size",
"OP_waittillmatch",
"OP_waittill",
"OP_notify",
"OP_endon",
"OP_voidCodepos",
"OP_switch",
"OP_endswitch",
"OP_vector",
"OP_NOP",
"OP_abort",
"OP_object",
"OP_thread_object",
"OP_EvalLocalVariable",
"OP_EvalLocalVariableRef",
"OP_prof_begin",
"OP_prof_end",
"OP_breakpoint",
"OP_assignmentBreakpoint",
"OP_manualAndAssignmentBreakpoint",
"OP_count"
};
std::string answer{};
int count = op_idx_rolled_over[inst] ? ARRAY_COUNT(op_history[inst]) : op_idx[inst];
for (auto i = 0; i < count; i++)
{
auto idx = op_idx[inst] - 1 - i;
if (idx < 0)
{
idx += ARRAY_COUNT(op_history[inst]);
}
if ((int)op_history[inst][idx] >= 0 && op_history[inst][idx] < game::OP_count)
{
answer += std::format("{}\n", OpcodeVMToString[op_history[inst][idx]]);
}
else
{
answer += std::format("0x{:02x}\n", (int)op_history[inst][idx]);
}
}
return answer;
}
std::string get_gsc_call_stack(game::scriptInstance_t inst)
{
std::string answer{};
int bufferIndex;
int prevSourcePos;
int col;
char line[1024];
int lineNum;
const char* fileName;
if (!game::gFs[inst].pos || !game::Scr_IsInOpcodeMemory(inst, game::gFs[inst].pos))
{
return answer;
}
for (auto frame = game::gScrVmPub[inst].function_frame_start;; frame++)
{
if (!frame->fs.pos || !game::Scr_IsInOpcodeMemory(inst, frame->fs.pos))
{
break;
}
bufferIndex = game::Scr_GetSourceBuffer(inst, frame->fs.pos - 1);
prevSourcePos = game::Scr_GetPrevSourcePos(inst, frame->fs.pos - 1, 0);
lineNum = game::Scr_GetLineInfo(&col, game::gScrParserPub[inst].sourceBufferLookup[bufferIndex].sourceBuf, prevSourcePos, line);
fileName = game::gScrParserPub[inst].sourceBufferLookup[bufferIndex].buf;
answer += std::format("{}({}, {}): '{}'\n", fileName, lineNum, col, line);
if (frame == game::gScrVmPub[inst].function_frame)
{
break;
}
}
return answer;
}
std::string get_full_gsc_state_str(game::scriptInstance_t inst)
{
nlohmann::json answer;
nlohmann::json answer{};
auto t = *game::gInst;
*game::gInst = inst;
answer["inst"] = inst;
answer["gScrVarPub"] = game::gScrVarPub[inst];
answer["stack"] = printStack();
answer["codeCallStack"] = printStack();
answer["gscCallStack"] = get_gsc_call_stack(inst);
answer["opHistory"] = build_op_history(inst);
*game::gInst = t;
return answer.dump(2);
}
void push_opcode_to_history(game::scriptInstance_t inst, game::OpcodeVM op)
{
assert(inst == 0 || inst == 1);
//assert((int)op >= 0 && op < game::OP_count);
op_history[inst][op_idx[inst]++] = op;
if (op_idx[inst] >= ARRAY_COUNT(op_history[inst]))
{
op_idx_rolled_over[inst] = true;
op_idx[inst] = 0;
}
}
void push_builtin_history(game::scriptInstance_t inst, int idx)
{
inst = inst;
idx = idx;
}
void push_codepos_history(game::scriptInstance_t inst, const char* pos)
{
inst = inst;
pos = pos;
}

View File

@ -38,6 +38,5 @@ namespace codsrc
int SL_ConvertFromString(game::scriptInstance_t inst, const char* str);
int SL_ConvertFromRefString(game::scriptInstance_t inst, game::RefString* refString);
game::RefString* GetRefString_0(game::scriptInstance_t inst, const char* str);
const char* SL_DebugConvertToString(unsigned int stringValue, game::scriptInstance_t inst);
const char* SL_ConvertToStringSafe(unsigned int id, game::scriptInstance_t inst);
}

View File

@ -1066,6 +1066,8 @@ namespace codsrc
gScrVmPub[inst].outparamcount = outparamcount;
}*/
push_builtin_history(inst, builtinIndex);
assert(builtinIndex >= 0);
assert(builtinIndex < 1024);
@ -1130,6 +1132,8 @@ namespace codsrc
gScrVmPub[inst].top = localFs.top - 1;
}*/
push_builtin_history(inst, builtinIndex);
assert(builtinIndex >= 0);
assert(builtinIndex < 1024);
@ -1292,6 +1296,10 @@ namespace codsrc
}
//
// our additions
push_codepos_history(inst, game::gFs[inst].pos);
//
assert(game::gFs[inst].pos);
}
@ -2682,7 +2690,7 @@ namespace codsrc
int currentCaseValue;
const char* currentCodePos;
do
do // Scr_ReadIntArray(2 * game::gCaseCount[inst])
{
currentCaseValue = game::Scr_ReadUnsignedInt(inst, &game::gFs[inst].pos);
currentCodePos = game::Scr_ReadCodePos(inst, &game::gFs[inst].pos);
@ -2712,6 +2720,10 @@ namespace codsrc
{
game::gOpcode[inst] = (game::OpcodeVM)game::Scr_ReadUnsignedByte(inst, &game::gFs[inst].pos);
interrupt_return:
// our addition
push_opcode_to_history(inst, game::gOpcode[inst]);
//
switch ( game::gOpcode[inst] )
{
case game::OP_End:

View File

@ -70,5 +70,8 @@
#include "game/structs.hpp"
#include "game/symbols.hpp"
std::string get_full_gsc_state_str(game::scriptInstance_t inst);
void push_opcode_to_history(game::scriptInstance_t inst, game::OpcodeVM op);
void push_builtin_history(game::scriptInstance_t inst, int idx);
void push_codepos_history(game::scriptInstance_t inst, const char* pos);
using namespace std::literals;