DBG: New expression function plugin system, string support
This commit is contained in:
parent
19069dcff8
commit
3ab89502cd
|
@ -158,6 +158,11 @@ bool _plugin_registerexprfunction(int pluginHandle, const char* name, int argc,
|
|||
return pluginexprfuncregister(pluginHandle, name, argc, cbFunction, userdata);
|
||||
}
|
||||
|
||||
bool _plugin_registerexprfunctionex(int pluginHandle, const char* name, const ValueType & returnType, const ValueType* argTypes, size_t argCount, CBPLUGINEXPRFUNCTIONEX cbFunction, void* userdata)
|
||||
{
|
||||
return pluginexprfuncregisterex(pluginHandle, name, returnType, argTypes, argCount, cbFunction, userdata);
|
||||
}
|
||||
|
||||
bool _plugin_unregisterexprfunction(int pluginHandle, const char* name)
|
||||
{
|
||||
return pluginexprfuncunregister(pluginHandle, name);
|
||||
|
|
|
@ -231,6 +231,25 @@ typedef struct
|
|||
GUIMENUTYPE hMenu;
|
||||
} PLUG_CB_MENUPREPARE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ValueTypeNumber,
|
||||
ValueTypeString,
|
||||
} ValueType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* ptr;
|
||||
bool isOwner;
|
||||
} StringValue;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ValueType type;
|
||||
duint number;
|
||||
StringValue string;
|
||||
} ExpressionValue;
|
||||
|
||||
//enums
|
||||
typedef enum
|
||||
{
|
||||
|
@ -280,7 +299,8 @@ typedef enum
|
|||
typedef void (*CBPLUGIN)(CBTYPE cbType, void* callbackInfo);
|
||||
typedef bool (*CBPLUGINCOMMAND)(int argc, char** argv);
|
||||
typedef void (*CBPLUGINSCRIPT)();
|
||||
typedef duint(*CBPLUGINEXPRFUNCTION)(int argc, duint* argv, void* userdata);
|
||||
typedef duint(*CBPLUGINEXPRFUNCTION)(int argc, const duint* argv, void* userdata);
|
||||
typedef bool(*CBPLUGINEXPRFUNCTIONEX)(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
typedef FORMATRESULT(*CBPLUGINFORMATFUNCTION)(char* dest, size_t destCount, int argc, char* argv[], duint value, void* userdata);
|
||||
typedef bool (*CBPLUGINPREDICATE)(void* userdata);
|
||||
|
||||
|
@ -316,6 +336,7 @@ PLUG_IMPEXP bool _plugin_menuentryremove(int pluginHandle, int hEntry);
|
|||
PLUG_IMPEXP void _plugin_startscript(CBPLUGINSCRIPT cbScript);
|
||||
PLUG_IMPEXP bool _plugin_waituntilpaused();
|
||||
PLUG_IMPEXP bool _plugin_registerexprfunction(int pluginHandle, const char* name, int argc, CBPLUGINEXPRFUNCTION cbFunction, void* userdata);
|
||||
PLUG_IMPEXP bool _plugin_registerexprfunctionex(int pluginHandle, const char* name, const ValueType & returnType, const ValueType* argTypes, size_t argCount, CBPLUGINEXPRFUNCTIONEX cbFunction, void* userdata);
|
||||
PLUG_IMPEXP bool _plugin_unregisterexprfunction(int pluginHandle, const char* name);
|
||||
PLUG_IMPEXP bool _plugin_unload(const char* pluginName);
|
||||
PLUG_IMPEXP bool _plugin_load(const char* pluginName);
|
||||
|
|
|
@ -21,20 +21,28 @@ struct gens<0, S...>
|
|||
};
|
||||
|
||||
template<typename T, int ...S, typename... Ts>
|
||||
static T callFunc(const T* argv, T(*cbFunction)(Ts...), seq<S...>)
|
||||
static duint callFunc(const T* argv, duint(*cbFunction)(Ts...), seq<S...>)
|
||||
{
|
||||
return cbFunction(argv[S]...);
|
||||
return cbFunction(argv[S].number...);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
static bool RegisterEasy(const String & name, duint(*cbFunction)(Ts...))
|
||||
{
|
||||
auto aliases = StringUtils::Split(name, ',');
|
||||
auto tempFunc = [cbFunction](int argc, duint * argv, void* userdata)
|
||||
auto tempFunc = [cbFunction](ExpressionValue * result, int argc, const ExpressionValue * argv, void* userdata) -> bool
|
||||
{
|
||||
return callFunc(argv, cbFunction, typename gens<sizeof...(Ts)>::type());
|
||||
result->type = ValueTypeNumber;
|
||||
result->number = callFunc(argv, cbFunction, typename gens<sizeof...(Ts)>::type());
|
||||
|
||||
return true;
|
||||
};
|
||||
if(!ExpressionFunctions::Register(aliases[0], sizeof...(Ts), tempFunc))
|
||||
std::vector<ValueType> args(sizeof...(Ts));
|
||||
|
||||
for(auto & arg : args)
|
||||
arg = ValueTypeNumber;
|
||||
|
||||
if(!ExpressionFunctions::Register(aliases[0], ValueTypeNumber, args, tempFunc))
|
||||
return false;
|
||||
for(size_t i = 1; i < aliases.size(); i++)
|
||||
ExpressionFunctions::RegisterAlias(aliases[0], aliases[i]);
|
||||
|
@ -143,9 +151,15 @@ void ExpressionFunctions::Init()
|
|||
|
||||
//Undocumented
|
||||
RegisterEasy("bpgoto", bpgoto);
|
||||
|
||||
ExpressionFunctions::Register("strcmp", ValueTypeNumber, { ValueTypeString, ValueTypeString }, Exprfunc::strcmp, nullptr);
|
||||
ExpressionFunctions::Register("strstr", ValueTypeNumber, { ValueTypeString, ValueTypeString }, Exprfunc::strstr, nullptr);
|
||||
ExpressionFunctions::Register("utf16", ValueTypeString, { ValueTypeNumber }, Exprfunc::utf16, nullptr);
|
||||
ExpressionFunctions::Register("utf8", ValueTypeString, { ValueTypeNumber }, Exprfunc::utf8, nullptr);
|
||||
ExpressionFunctions::Register("mod.fromname", ValueTypeNumber, { ValueTypeString }, Exprfunc::modbasefromname, nullptr);
|
||||
}
|
||||
|
||||
bool ExpressionFunctions::Register(const String & name, int argc, const CBEXPRESSIONFUNCTION & cbFunction, void* userdata)
|
||||
bool ExpressionFunctions::Register(const String & name, const ValueType & returnType, const std::vector<ValueType> & argTypes, const CBEXPRESSIONFUNCTION & cbFunction, void* userdata)
|
||||
{
|
||||
if(!isValidName(name))
|
||||
return false;
|
||||
|
@ -154,7 +168,8 @@ bool ExpressionFunctions::Register(const String & name, int argc, const CBEXPRES
|
|||
return false;
|
||||
Function f;
|
||||
f.name = name;
|
||||
f.argc = argc;
|
||||
f.argTypes = argTypes;
|
||||
f.returnType = returnType;
|
||||
f.cbFunction = cbFunction;
|
||||
f.userdata = userdata;
|
||||
mFunctions[name] = f;
|
||||
|
@ -167,8 +182,10 @@ bool ExpressionFunctions::RegisterAlias(const String & name, const String & alia
|
|||
auto found = mFunctions.find(name);
|
||||
if(found == mFunctions.end())
|
||||
return false;
|
||||
if(!Register(alias, found->second.argc, found->second.cbFunction, found->second.userdata))
|
||||
|
||||
if(!Register(alias, found->second.returnType, found->second.argTypes, found->second.cbFunction, found->second.userdata))
|
||||
return false;
|
||||
|
||||
found->second.aliases.push_back(alias);
|
||||
return true;
|
||||
}
|
||||
|
@ -186,29 +203,35 @@ bool ExpressionFunctions::Unregister(const String & name)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ExpressionFunctions::Call(const String & name, std::vector<duint> & argv, duint & result)
|
||||
bool ExpressionFunctions::Call(const String & name, ExpressionValue & result, std::vector<ExpressionValue> & argv)
|
||||
{
|
||||
SHARED_ACQUIRE(LockExpressionFunctions);
|
||||
auto found = mFunctions.find(name);
|
||||
if(found == mFunctions.end())
|
||||
return false;
|
||||
const auto & f = found->second;
|
||||
if(f.argc != int(argv.size()))
|
||||
if(f.argTypes.size() != int(argv.size()))
|
||||
return false;
|
||||
result = f.cbFunction(f.argc, argv.data(), f.userdata);
|
||||
return true;
|
||||
for(size_t i = 0; i < argv.size(); i++)
|
||||
{
|
||||
if(argv[i].type != f.argTypes[i])
|
||||
return false;
|
||||
}
|
||||
return f.cbFunction(&result, argv.size(), argv.data(), f.userdata);
|
||||
}
|
||||
|
||||
bool ExpressionFunctions::GetArgc(const String & name, int & argc)
|
||||
bool ExpressionFunctions::GetType(const String & name, ValueType & returnType, std::vector<ValueType> & argTypes)
|
||||
{
|
||||
SHARED_ACQUIRE(LockExpressionFunctions);
|
||||
auto found = mFunctions.find(name);
|
||||
if(found == mFunctions.end())
|
||||
return false;
|
||||
argc = found->second.argc;
|
||||
returnType = found->second.returnType;
|
||||
argTypes = found->second.argTypes;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ExpressionFunctions::isValidName(const String & name)
|
||||
{
|
||||
if(!name.length())
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
#include "_plugins.h"
|
||||
#include <functional>
|
||||
|
||||
|
||||
class ExpressionFunctions
|
||||
{
|
||||
public:
|
||||
using CBEXPRESSIONFUNCTION = std::function<duint(int argc, duint* argv, void* userdata)>;
|
||||
// TODO: also register the argument types
|
||||
using CBEXPRESSIONFUNCTION = std::function<bool(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)>;
|
||||
|
||||
static void Init();
|
||||
static bool Register(const String & name, int argc, const CBEXPRESSIONFUNCTION & cbFunction, void* userdata = nullptr);
|
||||
static bool Register(const String & name, const ValueType & returnType, const std::vector<ValueType> & argTypes, const CBEXPRESSIONFUNCTION & cbFunction, void* userdata = nullptr);
|
||||
static bool RegisterAlias(const String & name, const String & alias);
|
||||
static bool Unregister(const String & name);
|
||||
static bool Call(const String & name, std::vector<duint> & argv, duint & result);
|
||||
static bool GetArgc(const String & name, int & argc);
|
||||
static bool Call(const String & name, ExpressionValue & result, std::vector<ExpressionValue> & argv);
|
||||
static bool GetType(const String & name, ValueType & returnType, std::vector<ValueType> & argTypes);
|
||||
|
||||
private:
|
||||
struct Function
|
||||
{
|
||||
String name;
|
||||
int argc = 0;
|
||||
ValueType returnType;
|
||||
std::vector<ValueType> argTypes;
|
||||
CBEXPRESSIONFUNCTION cbFunction;
|
||||
void* userdata = nullptr;
|
||||
std::vector<String> aliases;
|
||||
|
|
|
@ -873,25 +873,76 @@ bool ExpressionParser::Calculate(duint & value, bool signedcalc, bool allowassig
|
|||
else if(token.type() == Token::Type::Function)
|
||||
{
|
||||
const auto & name = token.data();
|
||||
int argc;
|
||||
if(!ExpressionFunctions::GetArgc(name, argc))
|
||||
ValueType returnType;
|
||||
std::vector<ValueType> argTypes;
|
||||
if(!ExpressionFunctions::GetType(name, returnType, argTypes))
|
||||
return false;
|
||||
if(int(stack.size()) < argc)
|
||||
if(int(stack.size()) < argTypes.size())
|
||||
return false;
|
||||
std::vector<duint> argv;
|
||||
argv.resize(argc);
|
||||
for(auto i = 0; i < argc; i++)
|
||||
std::vector<ExpressionValue> argv;
|
||||
argv.resize(argTypes.size());
|
||||
for(auto i = 0; i < argTypes.size(); i++)
|
||||
{
|
||||
duint arg;
|
||||
/*duint arg;
|
||||
if(!stack[stack.size() - 1].DoEvaluate(arg, silent, baseonly))
|
||||
return false;
|
||||
stack.pop_back();
|
||||
argv[argc - i - 1] = arg;
|
||||
return false;*/
|
||||
// TODO: put in EvalValue -> ExpressionValue
|
||||
auto & top = stack[stack.size() - i - 1];
|
||||
ExpressionValue arg;
|
||||
if(top.evaluated)
|
||||
arg = { ValueTypeNumber, top.value };
|
||||
else
|
||||
{
|
||||
arg = { ValueTypeString, 0, StringValue{top.data.c_str(), false} };
|
||||
}
|
||||
|
||||
if(arg.type != argTypes[i])
|
||||
{
|
||||
if(arg.type == ValueTypeString)
|
||||
{
|
||||
duint result;
|
||||
|
||||
if(!top.DoEvaluate(result, silent, baseonly, value_size, isvar, hexonly))
|
||||
return false;
|
||||
|
||||
arg.number = result;
|
||||
if(arg.string.isOwner)
|
||||
BridgeFree((void*)arg.string.ptr);
|
||||
|
||||
arg.string.ptr = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
char str[32] = "";
|
||||
sprintf_s(str, "0x%p", arg.number);
|
||||
void* ptr = BridgeAlloc(sizeof(str));
|
||||
strcpy_s((char*)ptr, _countof(str), str);
|
||||
arg.string.ptr = (const char*)ptr;
|
||||
arg.string.isOwner = true;
|
||||
}
|
||||
|
||||
arg.type = argTypes[i];
|
||||
}
|
||||
|
||||
argv[argTypes.size() - i - 1] = arg;
|
||||
}
|
||||
duint result;
|
||||
if(!ExpressionFunctions::Call(name, argv, result))
|
||||
|
||||
ExpressionValue result = { ValueTypeNumber, 0 };
|
||||
if(!ExpressionFunctions::Call(name, result, argv))
|
||||
return false;
|
||||
stack.push_back(EvalValue(result));
|
||||
|
||||
for(size_t i = 0; i < argv.size(); i++)
|
||||
{
|
||||
stack.pop_back();
|
||||
}
|
||||
if(result.type == ValueTypeString)
|
||||
{
|
||||
stack.push_back(EvalValue(result.string.ptr));
|
||||
if(result.string.isOwner)
|
||||
BridgeFree((void*)result.string.ptr);
|
||||
}
|
||||
else
|
||||
stack.push_back(EvalValue(result.number));
|
||||
}
|
||||
else
|
||||
stack.push_back(EvalValue(token.data()));
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "value.h"
|
||||
#include "TraceRecord.h"
|
||||
#include "exhandlerinfo.h"
|
||||
#include <vector>
|
||||
|
||||
namespace Exprfunc
|
||||
{
|
||||
|
@ -181,7 +182,7 @@ namespace Exprfunc
|
|||
BASIC_INSTRUCTION_INFO info;
|
||||
if(!disasmfast(addr, &info, true))
|
||||
return 0;
|
||||
return info.branch && !info.call && !strstr(info.instruction, "jmp");
|
||||
return info.branch && !info.call && !::strstr(info.instruction, "jmp");
|
||||
}
|
||||
|
||||
duint disisbranch(duint addr)
|
||||
|
@ -197,7 +198,7 @@ namespace Exprfunc
|
|||
BASIC_INSTRUCTION_INFO info;
|
||||
if(!disasmfast(addr, &info, true))
|
||||
return 0;
|
||||
return strstr(info.instruction, "ret") != nullptr;
|
||||
return ::strstr(info.instruction, "ret") != nullptr;
|
||||
}
|
||||
|
||||
duint disiscall(duint addr)
|
||||
|
@ -271,7 +272,7 @@ namespace Exprfunc
|
|||
BASIC_INSTRUCTION_INFO info;
|
||||
if(!disasmfast(addr, &info, true))
|
||||
return 0;
|
||||
return info.branch && !strstr(info.instruction, "jmp") ? addr + info.size : 0;
|
||||
return info.branch && !::strstr(info.instruction, "jmp") ? addr + info.size : 0;
|
||||
}
|
||||
|
||||
duint disnext(duint addr)
|
||||
|
@ -471,4 +472,102 @@ namespace Exprfunc
|
|||
return 0;
|
||||
return getLastExceptionInfo().ExceptionRecord.ExceptionInformation[index];
|
||||
}
|
||||
|
||||
bool utf16(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
if(argc > 1 || !argc)
|
||||
return false;
|
||||
|
||||
assert(argv[0].type == ValueTypeNumber);
|
||||
duint addr = argv[0].number;
|
||||
|
||||
std::vector<wchar_t> tempStr(MAX_STRING_SIZE + 1);
|
||||
if(!DbgMemRead(addr, tempStr.data(), sizeof(wchar_t) * (tempStr.size() - 1)))
|
||||
{
|
||||
// TODO: fail or just return ""?
|
||||
}
|
||||
|
||||
auto utf8Str = StringUtils::Utf16ToUtf8(tempStr.data());
|
||||
|
||||
if(utf8Str.empty() && wcslen(tempStr.data()) > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto strBuf = BridgeAlloc(utf8Str.size() + 1);
|
||||
memcpy(strBuf, utf8Str.c_str(), utf8Str.size());
|
||||
|
||||
result->type = ValueTypeString;
|
||||
result->string.ptr = (const char*)strBuf;
|
||||
result->string.isOwner = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool utf8(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
if(argc > 1 || !argc)
|
||||
return false;
|
||||
|
||||
assert(argv[0].type == ValueTypeNumber);
|
||||
duint addr = argv[0].number;
|
||||
|
||||
std::vector<char> tempStr(MAX_STRING_SIZE + 1);
|
||||
if(!DbgMemRead(addr, tempStr.data(), tempStr.size() - 1))
|
||||
{
|
||||
//Todo
|
||||
}
|
||||
|
||||
auto strlen = ::strlen(tempStr.data());
|
||||
|
||||
auto strBuf = BridgeAlloc(strlen + 1);
|
||||
memcpy(strBuf, tempStr.data(), strlen + 1);
|
||||
|
||||
result->type = ValueTypeString;
|
||||
result->string.ptr = (const char*)strBuf;
|
||||
result->string.isOwner = true;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool modbasefromname(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
result->type = ValueTypeNumber;
|
||||
result->number = ModBaseFromName(argv[0].string.ptr);
|
||||
|
||||
if(!result->number)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strcmp(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
assert(argv[0].type == ValueTypeString);
|
||||
result->type = ValueTypeNumber;
|
||||
result->number = 0;
|
||||
|
||||
if(argc > 2 || argc <= 1)
|
||||
return false;
|
||||
|
||||
result->number = !::strcmp(argv[0].string.ptr, argv[1].string.ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strstr(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
assert(argv[0].type == ValueTypeString);
|
||||
result->type = ValueTypeNumber;
|
||||
result->number = 0;
|
||||
|
||||
//Todo: find a way to cancel this action if the user does not use the utf functions
|
||||
//I.e. argv[0].string.ptr will point to the address from the debugger 0xABAB as a string: strstr(0xABAB, "A")
|
||||
|
||||
if(argc > 2 || argc <= 1)
|
||||
return false;
|
||||
|
||||
result->number = ::strstr(argv[0].string.ptr, argv[1].string.ptr) != nullptr;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
#include "expressionfunctions.h"
|
||||
|
||||
namespace Exprfunc
|
||||
{
|
||||
|
@ -79,4 +80,10 @@ namespace Exprfunc
|
|||
duint exflags();
|
||||
duint exinfocount();
|
||||
duint exinfo(duint index);
|
||||
|
||||
bool strcmp(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool strstr(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool utf16(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool utf8(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool modbasefromname(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
}
|
|
@ -983,6 +983,26 @@ bool pluginmenuentryremove(int pluginHandle, int hEntry)
|
|||
return false;
|
||||
}
|
||||
|
||||
struct ExprFuncWrapper
|
||||
{
|
||||
void* user;
|
||||
int argc;
|
||||
CBPLUGINEXPRFUNCTION cbFunc;
|
||||
std::vector<duint> cbArgv;
|
||||
|
||||
static bool callback(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
auto cbUser = reinterpret_cast<ExprFuncWrapper*>(userdata);
|
||||
for(auto i = 0; i < argc; i++)
|
||||
cbUser->cbArgv.push_back(argv[i].number);
|
||||
|
||||
result->type = ValueTypeNumber;
|
||||
result->number = cbUser->cbFunc(argc, cbUser->cbArgv.data(), cbUser->user);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bool pluginexprfuncregister(int pluginHandle, const char* name, int argc, CBPLUGINEXPRFUNCTION cbFunction, void* userdata)
|
||||
{
|
||||
String plugName;
|
||||
|
@ -991,7 +1011,18 @@ bool pluginexprfuncregister(int pluginHandle, const char* name, int argc, CBPLUG
|
|||
PLUG_EXPRFUNCTION plugExprfunction;
|
||||
plugExprfunction.pluginHandle = pluginHandle;
|
||||
strcpy_s(plugExprfunction.name, name);
|
||||
if(!ExpressionFunctions::Register(name, argc, cbFunction, userdata))
|
||||
|
||||
ExprFuncWrapper* wrapper = new ExprFuncWrapper;
|
||||
wrapper->argc = argc;
|
||||
wrapper->cbFunc = cbFunction;
|
||||
wrapper->user = userdata;
|
||||
|
||||
std::vector<ValueType> args(argc);
|
||||
|
||||
for(auto & arg : args)
|
||||
arg = ValueTypeNumber;
|
||||
|
||||
if(!ExpressionFunctions::Register(name, ValueTypeNumber, args, wrapper->callback, wrapper))
|
||||
{
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN, %s] Expression function \"%s\" failed to register...\n"), plugName.c_str(), name);
|
||||
return false;
|
||||
|
@ -1003,6 +1034,33 @@ bool pluginexprfuncregister(int pluginHandle, const char* name, int argc, CBPLUG
|
|||
return true;
|
||||
}
|
||||
|
||||
bool pluginexprfuncregisterex(int pluginHandle, const char* name, const ValueType & returnType, const ValueType* argTypes, size_t argCount, CBPLUGINEXPRFUNCTIONEX cbFunction, void* userdata)
|
||||
{
|
||||
String plugName;
|
||||
if(!findPluginName(pluginHandle, plugName))
|
||||
return false;
|
||||
PLUG_EXPRFUNCTION plugExprfunction;
|
||||
plugExprfunction.pluginHandle = pluginHandle;
|
||||
strcpy_s(plugExprfunction.name, name);
|
||||
|
||||
std::vector<ValueType> argTypesVec(argCount);
|
||||
|
||||
for(auto i = 0; i < argCount; i++)
|
||||
argTypesVec[i] = argTypes[i];
|
||||
|
||||
if(!ExpressionFunctions::Register(name, returnType, argTypesVec, cbFunction, userdata))
|
||||
{
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN, %s] Expression function \"%s\" failed to register...\n"), plugName.c_str(), name);
|
||||
return false;
|
||||
}
|
||||
EXCLUSIVE_ACQUIRE(LockPluginExprfunctionList);
|
||||
pluginExprfunctionList.push_back(plugExprfunction);
|
||||
EXCLUSIVE_RELEASE();
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN, %s] Expression function \"%s\" registered!\n"), plugName.c_str(), name);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool pluginexprfuncunregister(int pluginHandle, const char* name)
|
||||
{
|
||||
String plugName;
|
||||
|
|
|
@ -98,6 +98,7 @@ void pluginmenuentrysethotkey(int pluginHandle, int hEntry, const char* hotkey);
|
|||
bool pluginmenuremove(int hMenu);
|
||||
bool pluginmenuentryremove(int pluginHandle, int hEntry);
|
||||
bool pluginexprfuncregister(int pluginHandle, const char* name, int argc, CBPLUGINEXPRFUNCTION cbFunction, void* userdata);
|
||||
bool pluginexprfuncregisterex(int pluginHandle, const char* name, const ValueType & returnType, const ValueType* argTypes, size_t argCount, CBPLUGINEXPRFUNCTIONEX cbFunction, void* userdata);
|
||||
bool pluginexprfuncunregister(int pluginHandle, const char* name);
|
||||
bool pluginformatfuncregister(int pluginHandle, const char* type, CBPLUGINFORMATFUNCTION cbFunction, void* userdata);
|
||||
bool pluginformatfuncunregister(int pluginHandle, const char* type);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "disasm_helper.h"
|
||||
#include "formatfunctions.h"
|
||||
|
||||
enum class ValueType
|
||||
enum class StringValueType
|
||||
{
|
||||
Unknown,
|
||||
SignedDecimal,
|
||||
|
@ -19,7 +19,7 @@ enum class ValueType
|
|||
Instruction
|
||||
};
|
||||
|
||||
static String printValue(FormatValueType value, ValueType type)
|
||||
static String printValue(FormatValueType value, StringValueType type)
|
||||
{
|
||||
duint valuint = 0;
|
||||
char string[MAX_STRING_SIZE] = "";
|
||||
|
@ -28,37 +28,37 @@ static String printValue(FormatValueType value, ValueType type)
|
|||
{
|
||||
switch(type)
|
||||
{
|
||||
case ValueType::Unknown:
|
||||
case StringValueType::Unknown:
|
||||
break;
|
||||
#ifdef _WIN64
|
||||
case ValueType::SignedDecimal:
|
||||
case StringValueType::SignedDecimal:
|
||||
result = StringUtils::sprintf("%lld", valuint);
|
||||
break;
|
||||
case ValueType::UnsignedDecimal:
|
||||
case StringValueType::UnsignedDecimal:
|
||||
result = StringUtils::sprintf("%llu", valuint);
|
||||
break;
|
||||
case ValueType::Hex:
|
||||
case StringValueType::Hex:
|
||||
result = StringUtils::sprintf("%llX", valuint);
|
||||
break;
|
||||
#else //x86
|
||||
case ValueType::SignedDecimal:
|
||||
case StringValueType::SignedDecimal:
|
||||
result = StringUtils::sprintf("%d", valuint);
|
||||
break;
|
||||
case ValueType::UnsignedDecimal:
|
||||
case StringValueType::UnsignedDecimal:
|
||||
result = StringUtils::sprintf("%u", valuint);
|
||||
break;
|
||||
case ValueType::Hex:
|
||||
case StringValueType::Hex:
|
||||
result = StringUtils::sprintf("%X", valuint);
|
||||
break;
|
||||
#endif //_WIN64
|
||||
case ValueType::Pointer:
|
||||
case StringValueType::Pointer:
|
||||
result = StringUtils::sprintf("%p", valuint);
|
||||
break;
|
||||
case ValueType::String:
|
||||
case StringValueType::String:
|
||||
if(disasmgetstringatwrapper(valuint, string, false))
|
||||
result = string;
|
||||
break;
|
||||
case ValueType::AddrInfo:
|
||||
case StringValueType::AddrInfo:
|
||||
{
|
||||
auto symbolic = SymGetSymbolicName(valuint);
|
||||
if(disasmgetstringatwrapper(valuint, string, false))
|
||||
|
@ -69,14 +69,14 @@ static String printValue(FormatValueType value, ValueType type)
|
|||
result.clear();
|
||||
}
|
||||
break;
|
||||
case ValueType::Module:
|
||||
case StringValueType::Module:
|
||||
{
|
||||
char mod[MAX_MODULE_SIZE] = "";
|
||||
ModNameFromAddr(valuint, mod, true);
|
||||
result = mod;
|
||||
}
|
||||
break;
|
||||
case ValueType::Instruction:
|
||||
case StringValueType::Instruction:
|
||||
{
|
||||
BASIC_INSTRUCTION_INFO info;
|
||||
if(!disasmfast(valuint, &info, true))
|
||||
|
@ -92,33 +92,33 @@ static String printValue(FormatValueType value, ValueType type)
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool typeFromCh(char ch, ValueType & type)
|
||||
static bool typeFromCh(char ch, StringValueType & type)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case 'd':
|
||||
type = ValueType::SignedDecimal;
|
||||
type = StringValueType::SignedDecimal;
|
||||
break;
|
||||
case 'u':
|
||||
type = ValueType::UnsignedDecimal;
|
||||
type = StringValueType::UnsignedDecimal;
|
||||
break;
|
||||
case 'p':
|
||||
type = ValueType::Pointer;
|
||||
type = StringValueType::Pointer;
|
||||
break;
|
||||
case 's':
|
||||
type = ValueType::String;
|
||||
type = StringValueType::String;
|
||||
break;
|
||||
case 'x':
|
||||
type = ValueType::Hex;
|
||||
type = StringValueType::Hex;
|
||||
break;
|
||||
case 'a':
|
||||
type = ValueType::AddrInfo;
|
||||
type = StringValueType::AddrInfo;
|
||||
break;
|
||||
case 'm':
|
||||
type = ValueType::Module;
|
||||
type = StringValueType::Module;
|
||||
break;
|
||||
case 'i':
|
||||
type = ValueType::Instruction;
|
||||
type = StringValueType::Instruction;
|
||||
break;
|
||||
default: //invalid format
|
||||
return false;
|
||||
|
@ -126,10 +126,10 @@ static bool typeFromCh(char ch, ValueType & type)
|
|||
return true;
|
||||
}
|
||||
|
||||
static const char* getArgExpressionType(const String & formatString, ValueType & type, String & complexArgs)
|
||||
static const char* getArgExpressionType(const String & formatString, StringValueType & type, String & complexArgs)
|
||||
{
|
||||
size_t toSkip = 0;
|
||||
type = ValueType::Hex;
|
||||
type = StringValueType::Hex;
|
||||
complexArgs.clear();
|
||||
if(formatString.size() > 2 && !isdigit(formatString[0]) && formatString[1] == ':') //simple type
|
||||
{
|
||||
|
@ -152,21 +152,21 @@ static const char* getArgExpressionType(const String & formatString, ValueType &
|
|||
return formatString.c_str() + toSkip;
|
||||
}
|
||||
|
||||
static unsigned int getArgNumType(const String & formatString, ValueType & type)
|
||||
static unsigned int getArgNumType(const String & formatString, StringValueType & type)
|
||||
{
|
||||
String complexArgs;
|
||||
auto expression = getArgExpressionType(formatString, type, complexArgs);
|
||||
unsigned int argnum = 0;
|
||||
if(!expression || sscanf_s(expression, "%u", &argnum) != 1)
|
||||
type = ValueType::Unknown;
|
||||
type = StringValueType::Unknown;
|
||||
return argnum;
|
||||
}
|
||||
|
||||
static String handleFormatString(const String & formatString, const FormatValueVector & values)
|
||||
{
|
||||
auto type = ValueType::Unknown;
|
||||
auto type = StringValueType::Unknown;
|
||||
auto argnum = getArgNumType(formatString, type);
|
||||
if(type != ValueType::Unknown && argnum < values.size())
|
||||
if(type != StringValueType::Unknown && argnum < values.size())
|
||||
return printValue(values.at(argnum), type);
|
||||
return GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "[Formatting Error]"));
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ static String printComplexValue(FormatValueType value, const String & complexArg
|
|||
|
||||
static String handleFormatStringInline(const String & formatString)
|
||||
{
|
||||
auto type = ValueType::Unknown;
|
||||
auto type = StringValueType::Unknown;
|
||||
String complexArgs;
|
||||
auto value = getArgExpressionType(formatString, type, complexArgs);
|
||||
if(!complexArgs.empty())
|
||||
|
|
Loading…
Reference in New Issue