mirror of
https://github.com/x64dbg/x64dbg.git
synced 2024-11-23 04:50:07 +00:00
WIP changes to expression functions
This commit is contained in:
parent
6f5e786a54
commit
426f47f89d
@ -280,7 +280,7 @@ 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 FORMATRESULT(*CBPLUGINFORMATFUNCTION)(char* dest, size_t destCount, int argc, char* argv[], duint value, void* userdata);
|
||||
typedef bool (*CBPLUGINPREDICATE)(void* userdata);
|
||||
|
||||
|
@ -20,8 +20,50 @@ struct gens<0, S...>
|
||||
typedef seq<S...> type;
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
struct front;
|
||||
|
||||
template<typename T>
|
||||
struct front<T>
|
||||
{
|
||||
using type = typename T;
|
||||
};
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
struct front<T, Ts...>
|
||||
{
|
||||
using type = typename T;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct front<>
|
||||
{
|
||||
using type = duint;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct registerHelper;
|
||||
|
||||
template<>
|
||||
struct registerHelper<duint>
|
||||
{
|
||||
bool operator()(const String & name, int argc, const ExpressionFunctions::CBEXPRESSIONFUNCTIONINT & cbFunction)
|
||||
{
|
||||
return ExpressionFunctions::RegisterInt(name, argc, cbFunction);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct registerHelper<const char*>
|
||||
{
|
||||
bool operator()(const String & name, int argc, const ExpressionFunctions::CBEXPRESSIONFUNCTIONSTR & cbFunction)
|
||||
{
|
||||
return ExpressionFunctions::RegisterStr(name, argc, cbFunction);
|
||||
}
|
||||
};
|
||||
|
||||
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]...);
|
||||
}
|
||||
@ -30,11 +72,11 @@ 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](int argc, const typename front<Ts...>::type * argv, void* userdata) -> duint
|
||||
{
|
||||
return callFunc(argv, cbFunction, typename gens<sizeof...(Ts)>::type());
|
||||
};
|
||||
if(!ExpressionFunctions::Register(aliases[0], sizeof...(Ts), tempFunc))
|
||||
if(!registerHelper<typename front<Ts...>::type>()(aliases[0], sizeof...(Ts), tempFunc))
|
||||
return false;
|
||||
for(size_t i = 1; i < aliases.size(); i++)
|
||||
ExpressionFunctions::RegisterAlias(aliases[0], aliases[i]);
|
||||
@ -68,6 +110,7 @@ void ExpressionFunctions::Init()
|
||||
RegisterEasy("mod.offset,mod.fileoffset", valvatofileoffset);
|
||||
RegisterEasy("mod.headerva", modheaderva);
|
||||
RegisterEasy("mod.isexport", modisexport);
|
||||
RegisterEasy("mod.fromname", ModBaseFromName);
|
||||
|
||||
//Process information
|
||||
RegisterEasy("peb,PEB", peb);
|
||||
@ -143,9 +186,12 @@ void ExpressionFunctions::Init()
|
||||
|
||||
//Undocumented
|
||||
RegisterEasy("bpgoto", bpgoto);
|
||||
|
||||
//String
|
||||
RegisterEasy("strcmp", strcmp);
|
||||
}
|
||||
|
||||
bool ExpressionFunctions::Register(const String & name, int argc, const CBEXPRESSIONFUNCTION & cbFunction, void* userdata)
|
||||
bool ExpressionFunctions::RegisterInt(const String & name, int argc, const CBEXPRESSIONFUNCTIONINT & cbFunction, void* userdata)
|
||||
{
|
||||
if(!isValidName(name))
|
||||
return false;
|
||||
@ -155,8 +201,28 @@ bool ExpressionFunctions::Register(const String & name, int argc, const CBEXPRES
|
||||
Function f;
|
||||
f.name = name;
|
||||
f.argc = argc;
|
||||
f.cbFunction = cbFunction;
|
||||
f.cbFunctionInt = cbFunction;
|
||||
f.cbFunctionStr = nullptr;
|
||||
f.userdata = userdata;
|
||||
f.strFunction = false;
|
||||
mFunctions[name] = f;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExpressionFunctions::RegisterStr(const String & name, int argc, const CBEXPRESSIONFUNCTIONSTR & cbFunction, void* userdata)
|
||||
{
|
||||
if(!isValidName(name))
|
||||
return false;
|
||||
EXCLUSIVE_ACQUIRE(LockExpressionFunctions);
|
||||
if(mFunctions.count(name))
|
||||
return false;
|
||||
Function f;
|
||||
f.name = name;
|
||||
f.argc = argc;
|
||||
f.cbFunctionInt = nullptr;
|
||||
f.cbFunctionStr = cbFunction;
|
||||
f.userdata = userdata;
|
||||
f.strFunction = true;
|
||||
mFunctions[name] = f;
|
||||
return true;
|
||||
}
|
||||
@ -167,8 +233,16 @@ 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))
|
||||
return false;
|
||||
if(found->second.strFunction)
|
||||
{
|
||||
if(!RegisterStr(alias, found->second.argc, found->second.cbFunctionStr, found->second.userdata))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!RegisterInt(alias, found->second.argc, found->second.cbFunctionInt, found->second.userdata))
|
||||
return false;
|
||||
}
|
||||
found->second.aliases.push_back(alias);
|
||||
return true;
|
||||
}
|
||||
@ -186,26 +260,40 @@ bool ExpressionFunctions::Unregister(const String & name)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExpressionFunctions::Call(const String & name, std::vector<duint> & argv, duint & result)
|
||||
bool ExpressionFunctions::CallInt(const String & name, std::vector<duint> & argv, duint & result)
|
||||
{
|
||||
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.argc != int(argv.size()) || f.strFunction)
|
||||
return false;
|
||||
result = f.cbFunction(f.argc, argv.data(), f.userdata);
|
||||
result = f.cbFunctionInt(f.argc, argv.data(), f.userdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExpressionFunctions::GetArgc(const String & name, int & argc)
|
||||
bool ExpressionFunctions::CallStr(const String & name, std::vector<const char*> & argv, duint & result)
|
||||
{
|
||||
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()) || !f.strFunction)
|
||||
return false;
|
||||
result = f.cbFunctionStr(f.argc, argv.data(), f.userdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExpressionFunctions::GetArgc(const String & name, int & argc, bool & strFunction)
|
||||
{
|
||||
SHARED_ACQUIRE(LockExpressionFunctions);
|
||||
auto found = mFunctions.find(name);
|
||||
if(found == mFunctions.end())
|
||||
return false;
|
||||
argc = found->second.argc;
|
||||
strFunction = found->second.strFunction;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6,23 +6,28 @@
|
||||
class ExpressionFunctions
|
||||
{
|
||||
public:
|
||||
using CBEXPRESSIONFUNCTION = std::function<duint(int argc, duint* argv, void* userdata)>;
|
||||
using CBEXPRESSIONFUNCTIONINT = std::function<duint(int argc, const duint* argv, void* userdata)>;
|
||||
using CBEXPRESSIONFUNCTIONSTR = std::function<duint(int argc, const char** argv, void* userdata)>;
|
||||
|
||||
static void Init();
|
||||
static bool Register(const String & name, int argc, const CBEXPRESSIONFUNCTION & cbFunction, void* userdata = nullptr);
|
||||
static bool RegisterInt(const String & name, int argc, const CBEXPRESSIONFUNCTIONINT & cbFunction, void* userdata = nullptr);
|
||||
static bool RegisterStr(const String & name, int argc, const CBEXPRESSIONFUNCTIONSTR & 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 CallInt(const String & name, std::vector<duint> & argv, duint & result);
|
||||
static bool CallStr(const String & name, std::vector<const char*> & argv, duint & result);
|
||||
static bool GetArgc(const String & name, int & argc, bool & strFunction);
|
||||
|
||||
private:
|
||||
struct Function
|
||||
{
|
||||
String name;
|
||||
int argc = 0;
|
||||
CBEXPRESSIONFUNCTION cbFunction;
|
||||
CBEXPRESSIONFUNCTIONINT cbFunctionInt;
|
||||
CBEXPRESSIONFUNCTIONSTR cbFunctionStr;
|
||||
void* userdata = nullptr;
|
||||
std::vector<String> aliases;
|
||||
bool strFunction = false;
|
||||
};
|
||||
|
||||
static bool isValidName(const String & name);
|
||||
|
@ -872,23 +872,45 @@ bool ExpressionParser::Calculate(duint & value, bool signedcalc, bool allowassig
|
||||
{
|
||||
const auto & name = token.data();
|
||||
int argc;
|
||||
if(!ExpressionFunctions::GetArgc(name, argc))
|
||||
bool strFunction;
|
||||
if(!ExpressionFunctions::GetArgc(name, argc, strFunction))
|
||||
return false;
|
||||
if(int(stack.size()) < argc)
|
||||
return false;
|
||||
std::vector<duint> argv;
|
||||
argv.resize(argc);
|
||||
for(auto i = 0; i < argc; i++)
|
||||
{
|
||||
duint arg;
|
||||
if(!stack[stack.size() - 1].DoEvaluate(arg, silent, baseonly))
|
||||
return false;
|
||||
stack.pop_back();
|
||||
argv[argc - i - 1] = arg;
|
||||
}
|
||||
|
||||
duint result;
|
||||
if(!ExpressionFunctions::Call(name, argv, result))
|
||||
return false;
|
||||
if(strFunction)
|
||||
{
|
||||
std::vector<const char*> argv;
|
||||
argv.resize(argc);
|
||||
for(auto i = 0; i < argc; i++)
|
||||
{
|
||||
auto & value = stack[stack.size() - i - 1];
|
||||
if(value.evaluated)
|
||||
value.data = StringUtils::sprintf("0x%p", value.value);
|
||||
argv[argc - i - 1] = value.data.c_str();
|
||||
}
|
||||
auto success = ExpressionFunctions::CallStr(name, argv, result);
|
||||
for(auto i = 0; i < argc; i++)
|
||||
stack.pop_back();
|
||||
if(!success)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<duint> argv;
|
||||
argv.resize(argc);
|
||||
for(auto i = 0; i < argc; i++)
|
||||
{
|
||||
duint arg;
|
||||
if(!stack[stack.size() - 1].DoEvaluate(arg, silent, baseonly))
|
||||
return false;
|
||||
stack.pop_back();
|
||||
argv[argc - i - 1] = arg;
|
||||
}
|
||||
if(!ExpressionFunctions::CallInt(name, argv, result))
|
||||
return false;
|
||||
}
|
||||
stack.push_back(EvalValue(result));
|
||||
}
|
||||
else
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "value.h"
|
||||
#include "TraceRecord.h"
|
||||
#include "exhandlerinfo.h"
|
||||
#include <vector>
|
||||
|
||||
namespace Exprfunc
|
||||
{
|
||||
@ -461,4 +462,14 @@ namespace Exprfunc
|
||||
return 0;
|
||||
return getLastExceptionInfo().ExceptionRecord.ExceptionInformation[index];
|
||||
}
|
||||
|
||||
duint strcmp(const char* addrStr, const char* str)
|
||||
{
|
||||
duint addr = 0;
|
||||
if(!convertNumber(addrStr, addr, 16))
|
||||
return 0;
|
||||
std::vector<char> cmp(strlen(str) + 1);
|
||||
DbgMemRead(addr, cmp.data(), cmp.size());
|
||||
return ::strcmp(cmp.data(), str);
|
||||
}
|
||||
}
|
||||
|
@ -79,4 +79,6 @@ namespace Exprfunc
|
||||
duint exflags();
|
||||
duint exinfocount();
|
||||
duint exinfo(duint index);
|
||||
|
||||
duint strcmp(const char* addr, const char* str);
|
||||
}
|
@ -991,7 +991,7 @@ 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))
|
||||
if(!ExpressionFunctions::RegisterInt(name, argc, cbFunction, userdata))
|
||||
{
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN, %s] Expression function \"%s\" failed to register...\n"), plugName.c_str(), name);
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user