diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/script/debugger | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/script/debugger')
20 files changed, 1746 insertions, 0 deletions
diff --git a/Src/Wasabi/api/script/debugger/api_makidebug.cpp b/Src/Wasabi/api/script/debugger/api_makidebug.cpp new file mode 100644 index 00000000..af819fd9 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/api_makidebug.cpp @@ -0,0 +1,20 @@ +#include <precomp.h> +#include "api_makidebug.h" + +#ifdef CBCLASS +#undef CBCLASS +#endif +#define CBCLASS api_makiDebuggerI +START_DISPATCH; + VCB(API_MAKIDEBUGGER_DEBUGGER_TRACE, debugger_trace); + CB(API_MAKIDEBUGGER_DEBUGGER_ISACTIVE, debugger_isActive); + CB(API_MAKIDEBUGGER_DEBUGGER_GETVIP, debugger_getVIP); + CB(API_MAKIDEBUGGER_DEBUGGER_GETVSD, debugger_getVSD); + CB(API_MAKIDEBUGGER_DEBUGGER_GETVCC, debugger_getVCC); + CB(API_MAKIDEBUGGER_DEBUGGER_GETVSP, debugger_getVSP); + CB(API_MAKIDEBUGGER_DEBUGGER_FILTEREVENT, debugger_filterEvent); + VCB(API_MAKIDEBUGGER_DEBUGGER_EVENTCOMPLETE, debugger_eventComplete); + CB(API_MAKIDEBUGGER_DEBUGGER_CREATEJITD, debugger_createJITD); + CB(API_MAKIDEBUGGER_DEBUGGER_READSTACK, debugger_readStack); + CB(API_MAKIDEBUGGER_DEBUGGER_GETCODEBLOCK, debugger_getCodeBlock); +END_DISPATCH; diff --git a/Src/Wasabi/api/script/debugger/api_makidebug.h b/Src/Wasabi/api/script/debugger/api_makidebug.h new file mode 100644 index 00000000..c55d130e --- /dev/null +++ b/Src/Wasabi/api/script/debugger/api_makidebug.h @@ -0,0 +1,134 @@ +#ifndef __API_MAKIDEBUG_H +#define __API_MAKIDEBUG_H + +/*--------------------------------------------------------- +api_makiDebugger + void debugger_trace(); + int debugger_isActive(); + int debugger_getVIP(); + int debugger_getVSD(); + int debugger_getVCC(); + int debugger_getVSP(); + int debugger_filterEvent(int vcpuid, int eventid); + void debugger_eventComplete(); + MakiJITD *debugger_createJITD(int vcpuid, int bringitup=1); + int debugger_readStack(int n); + int debugger_getCodeBlock(int vcpuid); +---------------------------------------------------------*/ + +#include <wasabicfg.h> + +#ifndef WASABI_COMPILE_SCRIPT +#error "This module requires the script api" +#endif + +#ifndef WASABI_COMPILE_MAKIDEBUG +#error "This module requires the script debugger api" +#endif + +#include <bfc/dispatch.h> +#include <api/script/scriptvar.h> + +class MakiJITD; + +class NOVTABLE api_makiDebugger : public Dispatchable { + public: + void debugger_trace(); + int debugger_isActive(); + int debugger_getVIP(); + int debugger_getVSD(); + int debugger_getVCC(); + int debugger_getVSP(); + int debugger_filterEvent(int vcpuid, int eventid); + void debugger_eventComplete(); + MakiJITD *debugger_createJITD(int vcpuid, int bringitup=1); + scriptVar debugger_readStack(int n); + const char *debugger_getCodeBlock(int vcpuid); + + enum { + API_MAKIDEBUGGER_DEBUGGER_TRACE = 0, + API_MAKIDEBUGGER_DEBUGGER_ISACTIVE = 10, + API_MAKIDEBUGGER_DEBUGGER_GETVIP = 20, + API_MAKIDEBUGGER_DEBUGGER_GETVSD = 30, + API_MAKIDEBUGGER_DEBUGGER_GETVCC = 40, + API_MAKIDEBUGGER_DEBUGGER_GETVSP = 50, + API_MAKIDEBUGGER_DEBUGGER_FILTEREVENT = 60, + API_MAKIDEBUGGER_DEBUGGER_EVENTCOMPLETE = 70, + API_MAKIDEBUGGER_DEBUGGER_CREATEJITD = 80, + API_MAKIDEBUGGER_DEBUGGER_READSTACK = 90, + API_MAKIDEBUGGER_DEBUGGER_GETCODEBLOCK = 100, + }; +}; + +inline void api_makiDebugger::debugger_trace() { + _voidcall(API_MAKIDEBUGGER_DEBUGGER_TRACE); +} + +inline int api_makiDebugger::debugger_isActive() { + return _call(API_MAKIDEBUGGER_DEBUGGER_ISACTIVE, (int)0); +} + +inline int api_makiDebugger::debugger_getVIP() { + return _call(API_MAKIDEBUGGER_DEBUGGER_GETVIP, (int)0); +} + +inline int api_makiDebugger::debugger_getVSD() { + return _call(API_MAKIDEBUGGER_DEBUGGER_GETVSD, (int)0); +} + +inline int api_makiDebugger::debugger_getVCC() { + return _call(API_MAKIDEBUGGER_DEBUGGER_GETVCC, (int)0); +} + +inline int api_makiDebugger::debugger_getVSP() { + return _call(API_MAKIDEBUGGER_DEBUGGER_GETVSP, (int)0); +} + +inline int api_makiDebugger::debugger_filterEvent(int vcpuid, int eventid) { + return _call(API_MAKIDEBUGGER_DEBUGGER_FILTEREVENT, (int)0, vcpuid, eventid); +} + +inline void api_makiDebugger::debugger_eventComplete() { + _voidcall(API_MAKIDEBUGGER_DEBUGGER_EVENTCOMPLETE); +} + +inline MakiJITD *api_makiDebugger::debugger_createJITD(int vcpuid, int bringitup) { + return _call(API_MAKIDEBUGGER_DEBUGGER_CREATEJITD, (MakiJITD *)NULL, vcpuid, bringitup); +} + +inline const char *api_makiDebugger::debugger_getCodeBlock(int vcpuid) { + return _call(API_MAKIDEBUGGER_DEBUGGER_GETCODEBLOCK, (const char *)NULL, vcpuid); +} + +inline scriptVar api_makiDebugger::debugger_readStack(int n) { + scriptVar v={0,0}; + return _call(API_MAKIDEBUGGER_DEBUGGER_READSTACK, v, n); +} + +class api_makiDebuggerI : public api_makiDebugger { + public: + virtual void debugger_trace()=0; + virtual int debugger_isActive()=0; + virtual int debugger_getVIP()=0; + virtual int debugger_getVSD()=0; + virtual int debugger_getVCC()=0; + virtual int debugger_getVSP()=0; + virtual int debugger_filterEvent(int vcpuid, int eventid)=0; + virtual void debugger_eventComplete()=0; + virtual MakiJITD *debugger_createJITD(int vcpuid, int bringitup=1)=0; + virtual scriptVar debugger_readStack(int n)=0; + virtual const char *debugger_getCodeBlock(int vcpuid)=0; + + protected: + RECVS_DISPATCH; +}; + +// {858E4B64-AF1E-4b64-8D27-EFFAD9F82BB4} +static const GUID makiDebugApiServiceGuid = +{ 0x858e4b64, 0xaf1e, 0x4b64, { 0x8d, 0x27, 0xef, 0xfa, 0xd9, 0xf8, 0x2b, 0xb4 } }; + +extern api_makiDebugger *debugApi; + +#endif + + diff --git a/Src/Wasabi/api/script/debugger/debugapi.cpp b/Src/Wasabi/api/script/debugger/debugapi.cpp new file mode 100644 index 00000000..31ffc9d9 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/debugapi.cpp @@ -0,0 +1,62 @@ +#include <precomp.h> +#include <api/script/debugger/debugapi.h> +#include <api/script/debugger/jitd.h> +#include <api/script/vcpu.h> + +api_makiDebugger *debugApi = NULL; + +MakiDebuggerApi::MakiDebuggerApi() +{ +} + +MakiDebuggerApi::~MakiDebuggerApi() { + +} + +void MakiDebuggerApi::debugger_trace() { + debugger.trace(); +} + +int MakiDebuggerApi::debugger_isActive() { + return debugger.isActive(); +} + +int MakiDebuggerApi::debugger_getVIP() { + return VCPU::VIP; +} + +int MakiDebuggerApi::debugger_getVSD() { + return VCPU::VSD; +} + +int MakiDebuggerApi::debugger_getVCC() { + return VCPU::VCC; +} + +int MakiDebuggerApi::debugger_getVSP() { + return VCPU::VSP; +} + +int MakiDebuggerApi::debugger_filterEvent(int vcpuid, int eventid) { + return debugger.filterEvent(vcpuid, eventid); +} + +void MakiDebuggerApi::debugger_eventComplete() { + debugger.eventComplete(); +} + +MakiJITD *MakiDebuggerApi::debugger_createJITD(int vcpuid, int bringitup) { + MakiJITD *jitd = debugger.createJITD(vcpuid); + if (bringitup) + jitd->setGlobalBreakpoint(1); + return jitd; +} + +scriptVar MakiDebuggerApi::debugger_readStack(int n) { + VCPUscriptVar v = VCPU::peekAt(n); + return v.v; +} + +const char *MakiDebuggerApi::debugger_getCodeBlock(int vcpuid) { + return VCPU::getCodeBlock(vcpuid); +} diff --git a/Src/Wasabi/api/script/debugger/debugapi.h b/Src/Wasabi/api/script/debugger/debugapi.h new file mode 100644 index 00000000..2b44fa4f --- /dev/null +++ b/Src/Wasabi/api/script/debugger/debugapi.h @@ -0,0 +1,28 @@ +#ifndef __MAKIDEBUGAPI_H +#define __MAKIDEBUGAPI_H + +#include <api/script/debugger/api_makidebug.h> +#include <api/script/debugger/vcpudebug.h> + +class MakiDebuggerApi : public api_makiDebuggerI { + public: + MakiDebuggerApi(); + virtual ~MakiDebuggerApi(); + + virtual void debugger_trace(); + virtual int debugger_isActive(); + virtual int debugger_getVIP(); + virtual int debugger_getVSD(); + virtual int debugger_getVCC(); + virtual int debugger_getVSP(); + virtual int debugger_filterEvent(int vcpuid, int eventid); + virtual void debugger_eventComplete(); + virtual MakiJITD *debugger_createJITD(int vcpuid, int bringitup=1); + virtual scriptVar debugger_readStack(int n); + virtual const char *debugger_getCodeBlock(int vcpuid); + + private: + VCPUDebugger debugger; +}; + +#endif diff --git a/Src/Wasabi/api/script/debugger/debuggerui.cpp b/Src/Wasabi/api/script/debugger/debuggerui.cpp new file mode 100644 index 00000000..692fdeee --- /dev/null +++ b/Src/Wasabi/api/script/debugger/debuggerui.cpp @@ -0,0 +1,11 @@ +#include <precomp.h> +#include "debuggerui.h" + +#ifdef CBCLASS +#undef CBCLASS +#endif +#define CBCLASS DebuggerUII +START_DISPATCH; + CB(DEBUGGERUI_MESSAGELOOP, messageLoop); + VCB(DEBUGGERUI_SETJITD, setJITD); +END_DISPATCH; diff --git a/Src/Wasabi/api/script/debugger/debuggerui.h b/Src/Wasabi/api/script/debugger/debuggerui.h new file mode 100644 index 00000000..6138b417 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/debuggerui.h @@ -0,0 +1,42 @@ +#ifndef __DEBUGGERUI_H +#define __DEBUGGERUI_H + +#include <bfc/dispatch.h> + +class MakiJITD; + +/*------------------------------------------- +DebuggerUI + int messageLoop(); + void setJITD(MakiJITD *jitd); +-------------------------------------------*/ + +class DebuggerUI : public Dispatchable { + public: + int messageLoop(); + void setJITD(MakiJITD *jitd); + + enum { + DEBUGGERUI_MESSAGELOOP = 0, + DEBUGGERUI_SETJITD = 10, + }; +}; + +inline int DebuggerUI::messageLoop() { + return _call(DEBUGGERUI_MESSAGELOOP, (int)0); +} + +inline void DebuggerUI::setJITD(MakiJITD *jitd) { + _voidcall(DEBUGGERUI_SETJITD, jitd); +} + +class DebuggerUII : public DebuggerUI { + public: + virtual int messageLoop()=0; + virtual void setJITD(MakiJITD *jitd)=0; + + protected: + RECVS_DISPATCH; +}; + +#endif
\ No newline at end of file diff --git a/Src/Wasabi/api/script/debugger/debugsymbols.cpp b/Src/Wasabi/api/script/debugger/debugsymbols.cpp new file mode 100644 index 00000000..e3b85980 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/debugsymbols.cpp @@ -0,0 +1,75 @@ +#include <precomp.h> +#include "debugsymbols.h" +#include <api/script/debugger/disasm.h> +#include <api/script/scriptmgr.h> +#include <api/script/debugger/sourcecodeline.h> +#include <api/script/vcpu.h> + +DebugSymbols::DebugSymbols(int _vcpuid) : disasm(_vcpuid) +{ + gotsymbols = 0; + SystemObject *so = SOM::getSystemObjectByScriptId(_vcpuid); + if (so != NULL) + binaryfilename = so->getFilename(); + + VCPUcodeBlock *cb = VCPU::getCodeBlockEntry(_vcpuid); + if (cb->debugsize != 0) { + gotsymbols = 1; + char *p = cb->debugsymbols; + int n = *(int *)p; p += 4; + while (n--) { + int s = *(int *)p; p += 4; + wchar_t *m = WMALLOC(s+1); + MEMCPY(m, p, s*sizeof(wchar_t)); + m[s] = 0; + StringW *temp = new StringW; + temp->own(m); + //files.addItem(new String(m)); + files.addItem(temp); + //FREE(m); + p+=s; + } + n = *(int *)p; p += 4; + while (n--) { + SourceCodeLineI *l = new SourceCodeLineI(); + l->setPointer(*(int *)p); p += 4; + l->setSourceFile(files[*(int *)p]->getValue()); p += 4; + l->setSourceFileLine(*(int *)p); p += 4; + SourceCodeLineI *last = lines.getLast(); + if (last != NULL) last->setLength(l->getPointer()-last->getPointer()); + lines.addItem(l); + } + SourceCodeLineI *last = lines.getLast(); + if (last != NULL) last->setLength(cb->size - last->getPointer()); + } +} + +DebugSymbols::~DebugSymbols() +{ + files.deleteAll(); + lines.deleteAll(); +} + +int DebugSymbols::getNumLines() { + if (!gotsymbols) return disasm.getNumLines(); + return lines.getNumItems(); +} + +int DebugSymbols::findLine(int pointer) { + if (!gotsymbols) return disasm.findLine(pointer); + int i; + for (i=0;i<lines.getNumItems();i++) { + SourceCodeLine *l = lines.enumItem(i); + int ip = l->getPointer(); + int il = l->getLength(); + if (pointer >= ip && pointer < ip+il) { + return i; + } + } + return -1; +} + +SourceCodeLine *DebugSymbols::enumLine(int n) { + if (!gotsymbols) return disasm.enumLine(n); + return lines.enumItem(n); +} diff --git a/Src/Wasabi/api/script/debugger/debugsymbols.h b/Src/Wasabi/api/script/debugger/debugsymbols.h new file mode 100644 index 00000000..26c23a9c --- /dev/null +++ b/Src/Wasabi/api/script/debugger/debugsymbols.h @@ -0,0 +1,38 @@ +#ifndef __DEBUGSYMBOLS_H +#define __DEBUGSYMBOLS_H + +#include <bfc/ptrlist.h> +#include <bfc/string/StringW.h> +#include "disasm.h" + +class SourceCodeLine; +class SourceCodeLineI; +class MakiDisassembler; + +class DebugSymbols { + + public: + + DebugSymbols(int vcpuid); + virtual ~DebugSymbols(); + + virtual int getNumLines(); + virtual int findLine(int pointer); + virtual SourceCodeLine *enumLine(int n); + + private: + + PtrList<SourceCodeLineI> lines; + MakiDisassembler disasm; + StringW binaryfilename; + int gotsymbols; + PtrList<StringW> files; + //PtrList<MakiVariable> vars; +}; + + + + + + +#endif
\ No newline at end of file diff --git a/Src/Wasabi/api/script/debugger/disasm.cpp b/Src/Wasabi/api/script/debugger/disasm.cpp new file mode 100644 index 00000000..7b3c17ee --- /dev/null +++ b/Src/Wasabi/api/script/debugger/disasm.cpp @@ -0,0 +1,193 @@ +#include <precomp.h> +#include <api/script/debugger/disasm.h> +#include <api/script/opcodes.h> +#include <api/script/vcpu.h> +#include <api/script/debugger/sourcecodeline.h> +// --------------------------------------------------------------------- + +typedef struct { + const wchar_t *opname; + unsigned __int8 opval; + int type; +} opentry; + +opentry _optable[] = { + {L"nop", OPCODE_NOP, OPCODE_TYPE_VOID}, + {L"push", OPCODE_PUSH, OPCODE_TYPE_VAR}, + {L"popi", OPCODE_POPI, OPCODE_TYPE_VOID}, + {L"pop", OPCODE_POP, OPCODE_TYPE_VAR}, + {L"set ", OPCODE_SET, OPCODE_TYPE_VOID}, + {L"retf", OPCODE_RETF, OPCODE_TYPE_VOID}, + {L"call", OPCODE_CALLC, OPCODE_TYPE_PTR}, + {L"call", OPCODE_CALLM, OPCODE_TYPE_DLF}, + {L"call", OPCODE_CALLM2, OPCODE_TYPE_NDLF}, + {L"umv", OPCODE_UMV, OPCODE_TYPE_DISCARD}, + {L"cmpeq", OPCODE_CMPEQ, OPCODE_TYPE_VOID}, + {L"cmpne", OPCODE_CMPNE, OPCODE_TYPE_VOID}, + {L"cmpa", OPCODE_CMPA, OPCODE_TYPE_VOID}, + {L"cmpae", OPCODE_CMPAE, OPCODE_TYPE_VOID}, + {L"cmpb", OPCODE_CMPB, OPCODE_TYPE_VOID}, + {L"cmpbe", OPCODE_CMPBE, OPCODE_TYPE_VOID}, + {L"jiz", OPCODE_JIZ, OPCODE_TYPE_PTR}, + {L"jnz", OPCODE_JNZ, OPCODE_TYPE_PTR}, + {L"jmp", OPCODE_JMP, OPCODE_TYPE_PTR}, + {L"incs", OPCODE_INCS, OPCODE_TYPE_VOID}, + {L"decs", OPCODE_DECS, OPCODE_TYPE_VOID}, + {L"incp", OPCODE_INCP, OPCODE_TYPE_VOID}, + {L"decp", OPCODE_DECP, OPCODE_TYPE_VOID}, + {L"add", OPCODE_ADD, OPCODE_TYPE_VOID}, + {L"sub", OPCODE_SUB, OPCODE_TYPE_VOID}, + {L"mul", OPCODE_MUL, OPCODE_TYPE_VOID}, + {L"div", OPCODE_DIV, OPCODE_TYPE_VOID}, + {L"mod", OPCODE_MOD, OPCODE_TYPE_VOID}, + {L"neg", OPCODE_NEG, OPCODE_TYPE_VOID}, + {L"shl", OPCODE_SHL, OPCODE_TYPE_VOID}, + {L"shr", OPCODE_SHR, OPCODE_TYPE_VOID}, + {L"bnot", OPCODE_BNOT, OPCODE_TYPE_VOID}, + {L"bxor", OPCODE_XOR, OPCODE_TYPE_VOID}, + {L"band", OPCODE_AND, OPCODE_TYPE_VOID}, + {L"bor", OPCODE_OR, OPCODE_TYPE_VOID}, + {L"not", OPCODE_NOT, OPCODE_TYPE_VOID}, + {L"and", OPCODE_LAND, OPCODE_TYPE_VOID}, + {L"or", OPCODE_LOR, OPCODE_TYPE_VOID}, + {L"del", OPCODE_DELETE, OPCODE_TYPE_VOID}, + {L"new", OPCODE_NEW, OPCODE_TYPE_CLASSID}, + {L"cmpl", OPCODE_CMPLT, OPCODE_TYPE_VOID}, +}; + +int MakiDisassembler::optable[256]; +int MakiDisassembler::optableready = 0; + + +MakiDisassembler::MakiDisassembler(int _vcpuid) { + if (!optableready) { + MEMSET(optable, 0, sizeof(optable)); + for (int i=0;i<sizeof(_optable)/sizeof(opentry);i++) { + opentry e = _optable[i]; + optable[e.opval] = i; + } + optableready = 1; + } + vcpuid = _vcpuid; + disassemble(); +} + +MakiDisassembler::~MakiDisassembler() { + lines.deleteAll(); +} + +int MakiDisassembler::getVCPUId() { + return vcpuid; +} + +int MakiDisassembler::getNumLines() { + return lines.getNumItems(); +} + +SourceCodeLine *MakiDisassembler::enumLine(int n) { + return lines.enumItem(n); +} + +int MakiDisassembler::findLine(int pointer) { + int i; + for (i=0;i<lines.getNumItems();i++) { + SourceCodeLine *l = lines.enumItem(i); + int ip = l->getPointer(); + int il = l->getLength(); + if (pointer >= ip && pointer < ip+il) { + return i; + } + } + return -1; +} + + +void MakiDisassembler::disassemble() { + int size; + const char *codeblock = VCPU::getCodeBlock(vcpuid, &size); + if (codeblock != NULL) { + + const char *p = codeblock; + + unsigned char opcode = OPCODE_NOP; + + while (p < codeblock+size) { + const char *start_of_instruction = p; + opcode = *p; + p+=sizeof(opcode); + + StringW inst; + int a = optable[opcode]; + int id; + int size = 0; + inst = _optable[a].opname; + switch (_optable[a].type) { + case OPCODE_TYPE_VOID: + size = 1; + break; + case OPCODE_TYPE_VAR: + id = *(int *)p; p+=sizeof(int); + inst += StringPrintfW(L" var %08X", id); + size = 5; + break; + case OPCODE_TYPE_PTR: + id = *(int *)p; p+=sizeof(int); + inst += StringPrintfW(L" %08X", id+(p-codeblock)); + size = 5; + break; + case OPCODE_TYPE_DLF: { + id = *(int *)p; p+=sizeof(int); + int np = *(int *)p; + if ((np & 0xFFFF0000) == 0xFFFF0000) { + p+=sizeof(int); + np &= 0xFFFF; + } else + np = -1; + int i = VCPU::dlfBase(vcpuid)+id; + if (i != -1) { + VCPUdlfEntry *e = VCPU::DLFentryTable.enumItem(i); + if (e != NULL) { + if (np != -1) inst += StringPrintfW(L"(%d)", np); + inst += L" "; + inst += e->functionName; + } + } + size = 5 + ((np == -1) ? 0 : 4); + break; + } + case OPCODE_TYPE_NDLF: { + id = *(int *)p; p+=sizeof(int); + int np = *p; p++; + int i = VCPU::dlfBase(vcpuid)+id; + if (i != -1) { + VCPUdlfEntry *e = VCPU::DLFentryTable.enumItem(i); + if (e != NULL) { + inst += StringPrintfW(L"(%d) ", np); + inst += e->functionName; + } + } + size = 6; + break; + } + case OPCODE_TYPE_CLASSID: { + id = *(int *)p; p+=sizeof(int); + const wchar_t *cn = WASABI_API_MAKI->vcpu_getClassName(vcpuid, id); + inst += L" "; + inst += cn; + size = 5; + break; + } + case OPCODE_TYPE_DISCARD: + id = *(int *)p; p+=sizeof(int); + size = 5; + break; + } + SourceCodeLineI *scl = new SourceCodeLineI(); + scl->setLine(inst), + scl->setPointer(start_of_instruction-codeblock); + scl->setLength(size); + lines.addItem(scl); + } + } +} + diff --git a/Src/Wasabi/api/script/debugger/disasm.h b/Src/Wasabi/api/script/debugger/disasm.h new file mode 100644 index 00000000..2d8d3c71 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/disasm.h @@ -0,0 +1,38 @@ +#ifndef __MakiDisassembler_H +#define __MakiDisassembler_H + +#include <bfc/ptrlist.h> + +class SourceCodeLine; +class SourceCodeLineI; + +enum { + OPCODE_TYPE_VOID = 0, + OPCODE_TYPE_VAR, + OPCODE_TYPE_PTR, + OPCODE_TYPE_DLF, + OPCODE_TYPE_NDLF, + OPCODE_TYPE_CLASSID, + OPCODE_TYPE_DISCARD, +}; + +class MakiDisassembler { + public: + MakiDisassembler(int vcpuid); + virtual ~MakiDisassembler(); + + int getVCPUId(); + int getNumLines(); + SourceCodeLine *enumLine(int n); + int findLine(int pointer); + + private: + void disassemble(); + PtrList<SourceCodeLineI> lines; + int vcpuid; + static int optable[256]; + static int optableready; +}; + + +#endif
\ No newline at end of file diff --git a/Src/Wasabi/api/script/debugger/jitd.cpp b/Src/Wasabi/api/script/debugger/jitd.cpp new file mode 100644 index 00000000..62bfa731 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/jitd.cpp @@ -0,0 +1,176 @@ +#include <precomp.h> +#include "jitd.h" +#include "jitdbreak.h" +#include <api/service/svcs/svc_debuggerui.h> +#include <api/service/svc_enum.h> +#include <api/script/debugger/vcpudebug.h> +#include <api/script/debugger/debuggerui.h> +#include <api/script/debugger/sdebuggerui.h> +#include <api/script/debugger/debugsymbols.h> + +MakiJITD::MakiJITD(VCPUDebugger *_debugger, int _vcpuid) { + vip = vsp = vsd = vcc = -1; + globalbreakpoint = 1; // fucko!! + onhold = 0; + debugger = _debugger; + vcpuid = _vcpuid; + uisvc = NULL; + ui = NULL; + simpleui = NULL; + codeblock = _debugger->getCodeBlock(vcpuid); + sysbp = new JITDBreakpoint(this, 0); + breakpoints.addItem(sysbp); + sysbp->setEnabled(0); + symbols = new DebugSymbols(_vcpuid); +} + +MakiJITD::~MakiJITD() { + breakpoints.deleteAll(); + if (uisvc != NULL) { + uisvc->destroyUI(ui); + WASABI_API_SVC->service_release(uisvc); + } + delete simpleui; + delete symbols; +} + +int MakiJITD::getVIP() { + return vip; +} + +int MakiJITD::getVCC() { + return vcc; +} + +int MakiJITD::getVSD() { + return vsd; +} + +int MakiJITD::getVSP() { + return vsp; +} + +int MakiJITD::isGlobalBreakpointSet() { + return globalbreakpoint; +} + +void MakiJITD::setGlobalBreakpoint(int s) { + globalbreakpoint = s; +} + +int MakiJITD::getNumBreakpoints() { + return breakpoints.getNumItems(); +} + +JITDBreakpoint *MakiJITD::enumBreakpoint(int n) { + return breakpoints.enumItem(n); +} + +JITDBreakpoint *MakiJITD::findBreakpoint(int pointer) { + int i; + for (i=0;i<breakpoints.getNumItems();i++) { + JITDBreakpoint *bp = breakpoints.enumItem(i); + if (bp->isEnabled() && bp->getPointer() == pointer) + return bp; + } + return NULL; +} + +void MakiJITD::addBreakpoint(int pointer) { + breakpoints.addItem(new JITDBreakpoint(this, pointer)); +} + +void MakiJITD::removeBreakpoint(JITDBreakpoint *breakpoint) { + breakpoints.removeItem(breakpoint); + delete breakpoint; +} + +void MakiJITD::clearAllBreakpoints() { + breakpoints.deleteAll(); +} + +int MakiJITD::getVCPUId() { + return vcpuid; +} + +void MakiJITD::trace() { + vip = debugger->getVIP(); + vsp = debugger->getVSP(); + vsd = debugger->getVSD(); + vcc = debugger->getVCC(); + + if (globalbreakpoint || findBreakpoint(vip)) { + enterUi(); + } +} + +int MakiJITD::isActive() { + return 1; +} + +void MakiJITD::enterUi() { + createUi(); + sysbp->setEnabled(0); + globalbreakpoint = 0; + onhold = 1; + int next_command = ui->messageLoop(); + onhold = 0; + switch (next_command) { + case JITD_RETURN_STEPINTO: + globalbreakpoint = 1; + break; + case JITD_RETURN_STEPOUT: + // for now, continue + break; + case JITD_RETURN_TERMINATE: + // for now, continue + break; + case JITD_RETURN_CONTINUE: + // do nothing + default: + break; + } +} + +void MakiJITD::createUi() { + if (ui != NULL) return; + waServiceFactory *f = WASABI_API_SVC->service_getServiceByGuid(SERVICE_DEBUGGERUI); + if (f != NULL) { + uisvc = castService<svc_debuggerUI>(f); + if (uisvc != NULL) { + ui = uisvc->createUI(); + ui->setJITD(this); + } + } else { + simpleui = new SimpleDebuggerUI(); + ui = simpleui; + ui->setJITD(this); + } +} + +int MakiJITD::isOnHold() { + return onhold; +} + +const char *MakiJITD::getCodeBlock() { + return codeblock; +} + +void MakiJITD::setSysBreakpoint(int pointer) { + sysbp->setPointer(pointer); + sysbp->setEnabled(1); +} + +int MakiJITD::getNumLines() { + return symbols->getNumLines(); +} + +SourceCodeLine *MakiJITD::enumLine(int n) { + return symbols->enumLine(n); +} + +int MakiJITD::findLine(int pointer) { + return symbols->findLine(pointer); +} + + diff --git a/Src/Wasabi/api/script/debugger/jitd.h b/Src/Wasabi/api/script/debugger/jitd.h new file mode 100644 index 00000000..6cb41f72 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/jitd.h @@ -0,0 +1,71 @@ +#ifndef __MAKIJITD_H +#define __MAKIJITD_H + +#include <bfc/ptrlist.h> + +class JITDBreakpoint; +class VCPUDebugger; +class svc_debuggerUI; +class SimpleDebuggerUI; +class DebuggerUI; +class DebugSymbols; +class SourceCodeLine; + +enum { + JITD_RETURN_STEPINTO = 0, + JITD_RETURN_STEPOVER = 1, + JITD_RETURN_STEPOUT = 2, + JITD_RETURN_TERMINATE = 3, + JITD_RETURN_CONTINUE = 4, +}; + +class MakiJITD { // dispatch me! + public: + MakiJITD(VCPUDebugger *debugger, int vcpuid); + virtual ~MakiJITD(); + + int getNumBreakpoints(); + JITDBreakpoint *enumBreakpoint(int n); + JITDBreakpoint *findBreakpoint(int pointer); + void addBreakpoint(int pointer); + void removeBreakpoint(JITDBreakpoint *breakpoint); + void clearAllBreakpoints(); + int isGlobalBreakpointSet(); + void setGlobalBreakpoint(int s); + void setSysBreakpoint(int pointer); // deactivates automatically next time the debugger is activated + int getVCPUId(); + void trace(); + int isActive(); + int isOnHold(); // 1 if running in the jitd's message loop + + int getVIP(); + int getVSD(); + int getVCC(); + int getVSP(); + + const char *getCodeBlock(); + + virtual int findLine(int pointer); + virtual int getNumLines(); + virtual SourceCodeLine *enumLine(int n); + + private: + void createUi(); + void enterUi(); + + int vcpuid; + int vip, vsd, vcc, vsp; + int globalbreakpoint; + + PtrList<JITDBreakpoint> breakpoints; + VCPUDebugger *debugger; + svc_debuggerUI *uisvc; + DebuggerUI *ui; + SimpleDebuggerUI *simpleui; + int onhold; + const char *codeblock; + JITDBreakpoint *sysbp; + DebugSymbols *symbols; +}; + +#endif
\ No newline at end of file diff --git a/Src/Wasabi/api/script/debugger/jitdbreak.cpp b/Src/Wasabi/api/script/debugger/jitdbreak.cpp new file mode 100644 index 00000000..4d12d3fe --- /dev/null +++ b/Src/Wasabi/api/script/debugger/jitdbreak.cpp @@ -0,0 +1,27 @@ +#include "precomp.h" +#include "jitdbreak.h" + +JITDBreakpoint::JITDBreakpoint(MakiJITD *_jitd, int _pointer) { + jitd = _jitd; + pointer = _pointer; + enabled = 1; +} + +JITDBreakpoint::~JITDBreakpoint() { +} + +int JITDBreakpoint::getPointer() { + return pointer; +} + +void JITDBreakpoint::setEnabled(int e) { + enabled = e; +} + +int JITDBreakpoint::isEnabled() { + return enabled; +} + +void JITDBreakpoint::setPointer(int _pointer) { + pointer = _pointer; +}
\ No newline at end of file diff --git a/Src/Wasabi/api/script/debugger/jitdbreak.h b/Src/Wasabi/api/script/debugger/jitdbreak.h new file mode 100644 index 00000000..960e83b6 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/jitdbreak.h @@ -0,0 +1,22 @@ +#ifndef __JITDBREAKPOINT_H +#define __JITDBREAKPOINT_H + +class MakiJITD; + +class JITDBreakpoint { + public: + JITDBreakpoint(MakiJITD *jitd, int pointer); + virtual ~JITDBreakpoint(); + + virtual int getPointer(); + virtual void setPointer(int pointer); + virtual void setEnabled(int e); + virtual int isEnabled(); + + private: + MakiJITD *jitd; + int pointer; + int enabled; +}; + +#endif diff --git a/Src/Wasabi/api/script/debugger/sdebuggerui.cpp b/Src/Wasabi/api/script/debugger/sdebuggerui.cpp new file mode 100644 index 00000000..c8349b05 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/sdebuggerui.cpp @@ -0,0 +1,437 @@ +#include <precomp.h> +#include "sdebuggerui.h" +#include <api/script/debugger/jitd.h> +#include <tataki/canvas/canvas.h> +#include <api/wnd/wndclass/editwnd.h> +#include <api/script/objcontroller.h> +#include <bfc/string/stringdict.h> +#include <bfc/parse/paramparser.h> +#include <api/wnd/notifmsg.h> +#include <api/script/objecttable.h> +#include <api/script/debugger/sourcecodeline.h> +#include "../nu/AutoWide.h" + +#define LEFTCOLUMN 100 +#define RIGHTCOLUMN 200 +#define INPUTHEIGHT 21 +#define NCONSOLELINES 4 +#define LINEHEIGHT 14 +#define REGWIDTH 100 + +SimpleDebuggerUI::SimpleDebuggerUI() +{ + leave = 0; + jitd = NULL; + edit = NULL; + memset(cmdbuf, 0, sizeof(cmdbuf)); + retcode = JITD_RETURN_CONTINUE; +} + +SimpleDebuggerUI::~SimpleDebuggerUI() +{} + +void SimpleDebuggerUI::setJITD(MakiJITD *_jitd) +{ + jitd = _jitd; +} + +int SimpleDebuggerUI::messageLoop() +{ + leave = 0; + retcode = JITD_RETURN_STEPINTO; + + if (!isInited()) + { + setVirtual(0); + setStartHidden(1); + setParent(WASABI_API_WND->main_getRootWnd()); + init(WASABI_API_WND->main_getRootWnd(), 1); + + edit = new EditWnd; + edit->setParent(this); + edit->setBackgroundColor(RGB(0, 0, 0)); + edit->setTextColor(RGB(0, 255, 0)); + edit->setWantFocus(0); + + *cmdbuf = 0; + edit->setBuffer(cmdbuf, 256); + edit->init(this); + + RECT r; + POINT pt = {0, 0}; + Wasabi::Std::getViewport(&r, &pt); + resize(r.right - 656, r.top + 16, 640, 480); + bringToFront(); + } + + for (int s = 0;s < jitd->getVSP();s++) + { + scriptVar v = WASABI_API_MAKIDEBUG->debugger_readStack(s); + StringW str; + switch (v.type) + { + case SCRIPT_VOID: + str = L"NULL"; + break; + case SCRIPT_INT: + str = StringPrintfW(L"%d", GET_SCRIPT_INT(v)); + break; + case SCRIPT_BOOLEAN: + str = StringPrintfW(L"%s", GET_SCRIPT_BOOLEAN(v) ? L"true" : L"false"); + break; + case SCRIPT_FLOAT: + str = StringPrintfW(L"%f", GET_SCRIPT_FLOAT(v)); + break; + case SCRIPT_DOUBLE: + str = StringPrintfW(L"%f", (float)GET_SCRIPT_DOUBLE(v)); + break; + case SCRIPT_STRING: + str = GET_SCRIPT_STRING(v); + break; + default: + { + if (v.type == SCRIPT_OBJECT) + str = L"Object"; + else + str = ObjectTable::getClassName(v.type); +#ifdef WASABI_COMPILE_SKIN + ScriptObject *o = GET_SCRIPT_OBJECT(v); + if (o != NULL) + { + GuiObject *go = static_cast<GuiObject *>(o->vcpu_getInterface(guiObjectGuid)); + if (go != NULL) + { + str += L";"; + str.cat(go->guiobject_getId()); + } + } +#endif + break; + } + } + strstack.addItem(new StringW(str)); + } + + setVisible(1); + + //WASABI_API_WND->pushModalWnd(this); + +#ifdef WIN32 + MSG msg; + //DWORD leavetime = GetTickCount()+5; + while (!leave/* && !(GetTickCount() >leavetime)*/) + { + if (PeekMessage(&msg, /*(HWND)NULL*/ getOsWindowHandle(), 0, 0, PM_NOREMOVE)) + { + GetMessage(&msg, /*(HWND) NULL*/getOsWindowHandle(), 0, 0) && + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +#endif + + //WASABI_API_WND->popModalWnd(this); + + setVisible(0); + strstack.deleteAll(); + + return retcode; +} + +int SimpleDebuggerUI::onPaint(Canvas *c) +{ + SimpleDebuggerUI_PARENT::onPaint(c); + Wasabi::FontInfo fontInfo; + RECT r; + getClientRect(&r); + c->fillRect(&r, RGB(0, 0, 0)); + c->drawRect(&r, 1, RGB(0, 255, 0)); + + fontInfo.color = RGB(0, 255, 0); + fontInfo.pointSize = 14; + fontInfo.face = L"Courier New"; + c->pushPen(PENSTYLE_SOLID, 1, RGB(0, 255, 0)); + c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8, StringPrintfW(L"VSD:%08X", jitd->getVSD()), &fontInfo); + c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1), StringPrintfW(L"VIP:%08X", jitd->getVIP()), &fontInfo); + c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1)*2, StringPrintfW(L"VSP:%08X", jitd->getVSP()), &fontInfo); + c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1)*3, StringPrintfW(L"VCC:%08X", jitd->getVCC()), &fontInfo); + c->lineDraw(r.left, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2), r.right, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2)); + c->lineDraw(r.left, r.bottom - (INPUTHEIGHT + 2), r.right - REGWIDTH, r.bottom - (INPUTHEIGHT + 2)); + c->lineDraw(r.right - REGWIDTH, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2), r.right - REGWIDTH, r.bottom); + c->lineDraw(r.right - RIGHTCOLUMN, 0, r.right - RIGHTCOLUMN, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2)); + disassemble(c); + for (int s = 0;s < strstack.getNumItems();s++) + { + c->textOutEllipsed(r.right - RIGHTCOLUMN + 4, s*LINEHEIGHT + 4, RIGHTCOLUMN - 8, 16, strstack.enumItem(s)->getValue(), &fontInfo); + } + return 1; +} + +int SimpleDebuggerUI::onLeftButtonDown(int x, int y) +{ + SimpleDebuggerUI_PARENT::onLeftButtonDown(x, y); + if (edit) edit->onGetFocus(); +// leave = 1; + return 1; +} + +void SimpleDebuggerUI::disassemble(Canvas *c) +{ + RECT r; + getClientRect(&r); + int x = 4; + + int y = (r.bottom - r.top - 4) / 2 + 4; + + int ln = jitd->findLine(jitd->getVIP()); + if (ln != -1) + { + Wasabi::FontInfo fontInfo; + SourceCodeLine *l = jitd->enumLine(ln); + int sourcecode = l->getSourceFile() != NULL; + int g; + int j = 0; + for (g = y;g < r.bottom - (INPUTHEIGHT + 4 + (NCONSOLELINES*LINEHEIGHT)) - LINEHEIGHT;g += LINEHEIGHT) + { + if (!sourcecode || j == 0) + l = jitd->enumLine(ln + j); + if (!l) break; + + if (j == 0) + { + RECT br; + br.left = 4; + br.top = g; + br.right = r.right - (RIGHTCOLUMN + 4); + br.bottom = br.top + LINEHEIGHT; + c->fillRect(&br, RGB(0, 255, 0)); + fontInfo.color = RGB(0, 0, 0); + } + if (!sourcecode) + { + String str; + unsigned const char *d = (unsigned const char *)(l->getPointer() + jitd->getCodeBlock()); + for (int k = 0;k < l->getLength();k++) + { + if (!str.isempty()) str += " "; + str += StringPrintf("%02X", *d); + d++; + } + c->textOut(x, g, StringPrintfW(L"%08X", l->getPointer()), &fontInfo); + c->textOut(x + 70, g, AutoWide(str), &fontInfo); + c->textOut(x + 70 + 150, g, l->getLine(), &fontInfo); + } + else + { + c->textOutEllipsed(x, g, r.right - r.left - (RIGHTCOLUMN + 4 + x), 16, (getLine(l->getSourceFile(), l->getSourceFileLine() + j)), &fontInfo); + } + + j++; + } + j = 1; + for (g = y - LINEHEIGHT;g > 1;g -= LINEHEIGHT) + { + if (!sourcecode || j == 0) + l = jitd->enumLine(ln - j); + if (!l) break; + if (!sourcecode) + { + String str; + unsigned const char *d = (unsigned const char *)(l->getPointer() + jitd->getCodeBlock()); + for (int k = 0;k < l->getLength();k++) + { + if (!str.isempty()) str += " "; + str += StringPrintf("%02X", *d); + d++; + } + c->textOut(x, g, StringPrintfW(L"%08X", l->getPointer()), &fontInfo); + c->textOut(x + 70, g, AutoWide(str), &fontInfo); + c->textOut(x + 70 + 150, g, (l->getLine()), &fontInfo); + } + else + { + c->textOutEllipsed(x, g, r.right - r.left - (RIGHTCOLUMN + 4 + x), 16, (getLine(l->getSourceFile(), l->getSourceFileLine() - j)), &fontInfo); + } + j++; + } + } +} + +int SimpleDebuggerUI::onResize() +{ + SimpleDebuggerUI_PARENT::onResize(); + if (edit != NULL) + { + RECT r; + getClientRect(&r); + edit->resize(1, r.bottom - (INPUTHEIGHT + 1), r.right - r.left - (REGWIDTH + 1), INPUTHEIGHT); + } + return 1; +} + +int SimpleDebuggerUI::childNotify(ifc_window *child, int msg, intptr_t p1, intptr_t p2) +{ + if (child == edit) + { + if (msg == ChildNotify::EDITWND_ENTER_PRESSED) + { + onCommand(cmdbuf); + } + } + return SimpleDebuggerUI_PARENT::childNotify(child, msg, p1, p2); +} + +BEGIN_STRINGDICTIONARY(_debuggercommands) +SDI(L"b", DEBUG_CMD_BREAKPOINT); +SDI(L"break", DEBUG_CMD_BREAKPOINT); +SDI(L"x", DEBUG_CMD_CONTINUE); +SDI(L"continue", DEBUG_CMD_CONTINUE); +SDI(L"i", DEBUG_CMD_STEPINTO); +SDI(L"stepinto", DEBUG_CMD_STEPINTO); +SDI(L"o", DEBUG_CMD_STEPOVER); +SDI(L"stepover", DEBUG_CMD_STEPOVER); +SDI(L"p", DEBUG_CMD_STEPOUT); +SDI(L"stepout", DEBUG_CMD_STEPOUT); +SDI(L"k", DEBUG_CMD_KILL); +SDI(L"kill", DEBUG_CMD_KILL); +SDI(L"?", DEBUG_CMD_HELP); +SDI(L"help", DEBUG_CMD_HELP); +END_STRINGDICTIONARY(_debuggercommands, debuggercommands) + + +void SimpleDebuggerUI::onCommand(const wchar_t *cmd) +{ + if (*cmd == 0) + { + stepOver(); + return; + } + ParamParser pp(cmd, L" "); + int i = debuggercommands.getId(pp.enumItem(0)); + switch (i) + { + case DEBUG_CMD_BREAKPOINT: + addBreakPoint(pp.enumItem(1)); + break; + case DEBUG_CMD_CONTINUE: + continueExecution(); + break; + case DEBUG_CMD_STEPINTO: + stepInto(); + break; + case DEBUG_CMD_STEPOVER: + stepOver(); + break; + case DEBUG_CMD_KILL: + killScript(); + break; + case DEBUG_CMD_HELP: + showHelp(); + break; + } +} + +int SimpleDebuggerUI::evaluate(const wchar_t *ascii) +{ + if (!_wcsicmp(ascii, L"VSD")) return jitd->getVSD(); + if (!_wcsicmp(ascii, L"VIP")) return jitd->getVIP(); + if (!_wcsicmp(ascii, L"VSP")) return jitd->getVSP(); + if (!_wcsicmp(ascii, L"VCC")) return jitd->getVCC(); + wchar_t *end; + return wcstol(ascii, &end, 16); +} + +void SimpleDebuggerUI::addBreakPoint(const wchar_t *pointer_ascii) +{ + /*int i = */evaluate(pointer_ascii); +} + +void SimpleDebuggerUI::continueExecution() +{ + retcode = JITD_RETURN_CONTINUE; + leave = 1; +} + +void SimpleDebuggerUI::stepInto() +{ + retcode = JITD_RETURN_STEPINTO; + leave = 1; +} + +void SimpleDebuggerUI::stepOver() +{ + int ln = jitd->findLine(jitd->getVIP()); + ln++; + SourceCodeLine *l = jitd->enumLine(ln); + + if (l != NULL) // else ret as last opcode + jitd->setSysBreakpoint(l->getPointer()); + + retcode = JITD_RETURN_CONTINUE; + leave = 1; +} + +void SimpleDebuggerUI::killScript() +{ + retcode = JITD_RETURN_TERMINATE; + leave = 1; +} + +void SimpleDebuggerUI::showHelp() +{} + +int SimpleDebuggerUI::onGetFocus() +{ + SimpleDebuggerUI_PARENT::onGetFocus(); + if (edit) edit->onGetFocus(); + return 1; +} + +void SimpleDebuggerUI::onSetVisible(int show) +{ + SimpleDebuggerUI_PARENT::onSetVisible(show); + if (edit) edit->onGetFocus(); +} +#undef fgets +const wchar_t *SimpleDebuggerUI::getLine(const wchar_t *filename, int fileline) +{ + if (fileline <= 0) + return L""; + static StringW str; + FILE *f = _wfopen(filename, L"rt"); + if (!f) + { + str = L"couldn't load "; + str += filename; + return str; + } + + char t[256] = {0}; + char u[256] = {0}; + int n = fileline; + while (n--) + { + *u = 0; + char *p; + do + { + p = *u ? t : u; + fgets(p, 255, f); + t[255] = 0; + } + while (!feof(f) && p[STRLEN(p)-1] != '\n' && p[STRLEN(p)-1] != '\r'); + } + + char *p = u; + while (p && *p && p < u + 256) + { + if (*p < 0x21) *p = ' '; + p++; + } + + str = AutoWide(u, CP_UTF8); + fclose(f); + + return str; +} + diff --git a/Src/Wasabi/api/script/debugger/sdebuggerui.h b/Src/Wasabi/api/script/debugger/sdebuggerui.h new file mode 100644 index 00000000..39f73ee5 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/sdebuggerui.h @@ -0,0 +1,65 @@ +#ifndef __SIMPLEDEBUGGERUI_H +#define __SIMPLEDEBUGGERUI_H + +#include "debuggerui.h" +#include <api/wnd/wndclass/clickwnd.h> + +class MakiDisassembler; +class EditWnd; +class String; +class SourceCodeLine; + +#define SimpleDebuggerUI_PARENT ClickWnd + +enum { + DEBUG_CMD_BREAKPOINT = 0, + DEBUG_CMD_CONTINUE, + DEBUG_CMD_STEPINTO, + DEBUG_CMD_STEPOVER, + DEBUG_CMD_STEPOUT, + DEBUG_CMD_KILL, + DEBUG_CMD_HELP, +}; + + +class MakiJITD; + +class SimpleDebuggerUI : public SimpleDebuggerUI_PARENT, public DebuggerUII { + public: + SimpleDebuggerUI(); + virtual ~SimpleDebuggerUI(); + + virtual int onPaint(Canvas *c); + virtual int onLeftButtonDown(int x, int y); + virtual int onResize(); + virtual int childNotify(ifc_window *child, int msg, intptr_t p1, intptr_t p2); + virtual void onSetVisible(int show); + + virtual int messageLoop(); + virtual void setJITD(MakiJITD *jitd); + + virtual void disassemble(Canvas *c); + virtual void onCommand(const wchar_t *cmd); + + virtual void addBreakPoint(const wchar_t *pointer_ascii); + virtual void continueExecution(); + virtual void stepInto(); + virtual void stepOver(); + virtual void killScript(); + virtual void showHelp(); + virtual int onGetFocus(); + + virtual int evaluate(const wchar_t *ascii); + virtual const wchar_t *getLine(const wchar_t *filename, int fileline); + + private: + + int leave; + MakiJITD *jitd; + EditWnd *edit; + wchar_t cmdbuf[256]; + int retcode; + PtrList<StringW> strstack; +}; + +#endif
\ No newline at end of file diff --git a/Src/Wasabi/api/script/debugger/sourcecodeline.cpp b/Src/Wasabi/api/script/debugger/sourcecodeline.cpp new file mode 100644 index 00000000..b6511c2b --- /dev/null +++ b/Src/Wasabi/api/script/debugger/sourcecodeline.cpp @@ -0,0 +1,69 @@ +#include <precomp.h> +#include "sourcecodeline.h" + +#ifdef CBCLASS +#undef CBCLASS +#endif +#define CBCLASS SourceCodeLineI +START_DISPATCH; + CB(SOURCECODELINE_GETLINE, getLine); + VCB(SOURCECODELINE_SETLINE, setLine); + CB(SOURCECODELINE_GETPOINTER, getPointer); + VCB(SOURCECODELINE_SETPOINTER, setPointer); + CB(SOURCECODELINE_GETLENGTH, getLength); + VCB(SOURCECODELINE_SETLENGTH, setLength); + VCB(SOURCECODELINE_SETSOURCEFILE, setSourceFile); + CB(SOURCECODELINE_GETSOURCEFILE, getSourceFile); + VCB(SOURCECODELINE_SETSOURCEFILELINE, setSourceFileLine); + CB(SOURCECODELINE_GETSOURCEFILELINE, getSourceFileLine); +END_DISPATCH; + +SourceCodeLineI::SourceCodeLineI() { + pointer = -1; + fileline = -1; + length = 0; +} + +SourceCodeLineI::~SourceCodeLineI() { +} + +const wchar_t *SourceCodeLineI::getLine() +{ + return line; +} + +void SourceCodeLineI::setLine(const wchar_t *_line) { + line = _line; +} + +int SourceCodeLineI::getPointer() { + return pointer; +} + +void SourceCodeLineI::setPointer(int _pointer) { + pointer = _pointer; +} + +int SourceCodeLineI::getLength() { + return length; +} + +void SourceCodeLineI::setLength(int _length) { + length = _length; +} + +void SourceCodeLineI::setSourceFile(const wchar_t *_file) { + file = _file; +} + +const wchar_t *SourceCodeLineI::getSourceFile() { + return file; +} + +void SourceCodeLineI::setSourceFileLine(int _linenumber) { + fileline = _linenumber; +} + +int SourceCodeLineI::getSourceFileLine() { + return fileline; +}
\ No newline at end of file diff --git a/Src/Wasabi/api/script/debugger/sourcecodeline.h b/Src/Wasabi/api/script/debugger/sourcecodeline.h new file mode 100644 index 00000000..a3a341ac --- /dev/null +++ b/Src/Wasabi/api/script/debugger/sourcecodeline.h @@ -0,0 +1,100 @@ +#ifndef __SOURCECODELINE_H +#define __SOURCECODELINE_H + +#include <bfc/dispatch.h> +#include <bfc/string/StringW.h> + + +class SourceCodeLine : public Dispatchable { + public: + const wchar_t *getLine(); + void setLine(const wchar_t *line); + int getPointer(); + void setPointer(int pointer); + int getLength(); + void setLength(int length); + void setSourceFile(const wchar_t *file); + const wchar_t *getSourceFile(); + void setSourceFileLine(int linenumber); + int getSourceFileLine(); + + enum { + SOURCECODELINE_GETLINE = 0, + SOURCECODELINE_SETLINE = 10, + SOURCECODELINE_GETPOINTER = 20, + SOURCECODELINE_SETPOINTER = 30, + SOURCECODELINE_GETLENGTH = 40, + SOURCECODELINE_SETLENGTH = 50, + SOURCECODELINE_SETSOURCEFILE = 60, + SOURCECODELINE_GETSOURCEFILE = 70, + SOURCECODELINE_SETSOURCEFILELINE = 80, + SOURCECODELINE_GETSOURCEFILELINE = 90, + }; +}; + +inline const wchar_t *SourceCodeLine::getLine() { + return _call(SOURCECODELINE_GETLINE, (const wchar_t*)NULL); +} + +inline void SourceCodeLine::setLine(const wchar_t *line) { + _voidcall(SOURCECODELINE_SETLINE, line); +} + +inline int SourceCodeLine::getPointer() { + return _call(SOURCECODELINE_GETPOINTER, (int)0); +} + +inline void SourceCodeLine::setPointer(int pointer) { + _voidcall(SOURCECODELINE_SETPOINTER, pointer); +} + +inline int SourceCodeLine::getLength() { + return _call(SOURCECODELINE_GETLENGTH, (int)0); +} + +inline void SourceCodeLine::setLength(int length) { + _voidcall(SOURCECODELINE_SETLENGTH, length); +} + +inline void SourceCodeLine::setSourceFile(const wchar_t *file) { + _voidcall(SOURCECODELINE_SETSOURCEFILE, file); +} + +inline const wchar_t *SourceCodeLine::getSourceFile() { + return _call(SOURCECODELINE_GETSOURCEFILE, (const wchar_t *)0); +} + +inline void SourceCodeLine::setSourceFileLine(int linenumber) { + _voidcall(SOURCECODELINE_SETSOURCEFILELINE, linenumber); +} + +inline int SourceCodeLine::getSourceFileLine() { + return _call(SOURCECODELINE_GETSOURCEFILELINE, (int)0); +} + +class SourceCodeLineI : public SourceCodeLine { + public: + SourceCodeLineI(); + virtual ~SourceCodeLineI(); + virtual const wchar_t *getLine(); + virtual void setLine(const wchar_t *line); + virtual int getPointer(); + virtual void setPointer(int pointer); + virtual int getLength(); + virtual void setLength(int length); + virtual void setSourceFile(const wchar_t *file); + virtual const wchar_t *getSourceFile(); + virtual void setSourceFileLine(int linenumber); + virtual int getSourceFileLine(); + + protected: + RECVS_DISPATCH; + + StringW line; + StringW file; + int fileline; + int pointer; + int length; +}; + +#endif
\ No newline at end of file diff --git a/Src/Wasabi/api/script/debugger/vcpudebug.cpp b/Src/Wasabi/api/script/debugger/vcpudebug.cpp new file mode 100644 index 00000000..94087956 --- /dev/null +++ b/Src/Wasabi/api/script/debugger/vcpudebug.cpp @@ -0,0 +1,99 @@ +#include <precomp.h> +#include <wasabicfg.h> +#include "vcpudebug.h" +#include <api/script/debugger/jitd.h> + +VCPUDebugger::VCPUDebugger() { + filter.setFilterObject(&reentryfilter); +} + +VCPUDebugger::~VCPUDebugger() { +} + +// ------------------------------------------------------------------------ + +// instruction pointer +int VCPUDebugger::getVIP() { + return WASABI_API_MAKIDEBUG->debugger_getVIP(); +} + +// script descriptor (vcpuid) +int VCPUDebugger::getVSD() { + return WASABI_API_MAKIDEBUG->debugger_getVSD(); +} + +// variables stack pointer +int VCPUDebugger::getVSP() { + return WASABI_API_MAKIDEBUG->debugger_getVSP(); +} + +// call stack pointer +int VCPUDebugger::getVCC() { + return WASABI_API_MAKIDEBUG->debugger_getVCC(); +} + +// ------------------------------------------------------------------------ +void VCPUDebugger::trace() { + int i; + for (i=0;i<jitds.getNumItems();i++) { + MakiJITD *jitd = jitds.enumItem(i); + if (jitd->getVCPUId() == getVSD()) { + jitd->trace(); + } + } +} + +MakiJITD *VCPUDebugger::getJITD(int vcpuid) { + int i; + for (i=0;i<jitds.getNumItems();i++) { + MakiJITD *jitd = jitds.enumItem(i); + if (jitd->getVCPUId() == vcpuid) + return jitd; + } + return NULL; +} + +// if this returns 1, you should not call eventComplete! +int VCPUDebugger::filterEvent(int vcpuid, int eventid) { + MakiJITD *jitd = getJITD(vcpuid); + if (!jitd || !jitd->isOnHold()) { + WASABI_API_WND->pushModalWnd(); + scopestack.push(0); + return 0; + } + filter.enterScope((vcpuid<<16) + eventid); // (vcpuid<<16) + eventid + if (filter.mustLeave()) { + filter.leaveScope(); + return 1; + } + WASABI_API_WND->pushModalWnd(); + scopestack.push(1); + return 0; +} + +void VCPUDebugger::eventComplete() { + int n; + scopestack.pop(&n); + WASABI_API_WND->popModalWnd(); + if (n) { + filter.leaveScope(); + } +} + +int VCPUDebugger::isActive() { + foreach(jitds) + if (jitds.getfor()->isActive()) + return 1; + endfor; + return 0; +} + +MakiJITD *VCPUDebugger::createJITD(int vcpuid) { + MakiJITD *jitd = new MakiJITD(this, vcpuid); + jitds.addItem(jitd); + return jitd; +} + +const char *VCPUDebugger::getCodeBlock(int vcpuid) { + return WASABI_API_MAKIDEBUG->debugger_getCodeBlock(vcpuid); +} diff --git a/Src/Wasabi/api/script/debugger/vcpudebug.h b/Src/Wasabi/api/script/debugger/vcpudebug.h new file mode 100644 index 00000000..6bba084b --- /dev/null +++ b/Src/Wasabi/api/script/debugger/vcpudebug.h @@ -0,0 +1,39 @@ +#ifndef __VCPUDEBUG_H +#define __VCPUDEBUG_H + +#include <bfc/ptrlist.h> +#include <bfc/stack.h> +#include <bfc/reentryfilter.h> + +class MakiJITD; + +class VCPUDebugger { + public: + VCPUDebugger(); + virtual ~VCPUDebugger(); + + void trace(); + + int getVIP(); // instruction pointer + int getVSD(); // script descriptor (id) + int getVSP(); // variables stack pointer + int getVCC(); // call stack pointer + + int filterEvent(int vcpuid, int eventid); // if this returns 1, you should return immediatly and not call eventComplete! + void eventComplete(); + + int isActive(); + + MakiJITD *createJITD(int vcpuid); + MakiJITD *getJITD(int vcpuid); + const char *getCodeBlock(int vcpuid); + + private: + + PtrList<MakiJITD> jitds; + ReentryFilterObject reentryfilter; + ReentryFilter filter; + Stack<int> scopestack; +}; + +#endif |