160 lines
4.0 KiB
C++
160 lines
4.0 KiB
C++
#include "argument.h"
|
|
#include "module.h"
|
|
#include "memory.h"
|
|
#include "threading.h"
|
|
|
|
struct ArgumentSerializer : JSONWrapper<ARGUMENTSINFO>
|
|
{
|
|
bool Save(const ARGUMENTSINFO & value) override
|
|
{
|
|
setString("module", value.mod);
|
|
setHex("start", value.start);
|
|
setHex("end", value.end);
|
|
setHex("icount", value.instructioncount);
|
|
setBool("manual", value.manual);
|
|
return true;
|
|
}
|
|
|
|
bool Load(ARGUMENTSINFO & value) override
|
|
{
|
|
return getString("module", value.mod) &&
|
|
getHex("start", value.start) &&
|
|
getHex("end", value.end) &&
|
|
getBool("manual", value.manual) &&
|
|
getHex("icount", value.instructioncount) &&
|
|
value.end >= value.start;
|
|
}
|
|
};
|
|
|
|
struct Arguments : SerializableModuleRangeMap<LockArguments, ARGUMENTSINFO, ArgumentSerializer>
|
|
{
|
|
void AdjustValue(ARGUMENTSINFO & value) const override
|
|
{
|
|
auto base = ModBaseFromName(value.mod);
|
|
value.start += base;
|
|
value.end += base;
|
|
}
|
|
|
|
protected:
|
|
const char* jsonKey() const override
|
|
{
|
|
return "arguments";
|
|
}
|
|
|
|
ModuleRange makeKey(const ARGUMENTSINFO & value) const override
|
|
{
|
|
return ModuleRange(ModHashFromName(value.mod), Range(value.start, value.end));
|
|
}
|
|
};
|
|
|
|
static Arguments arguments;
|
|
|
|
bool ArgumentAdd(duint Start, duint End, bool Manual, duint InstructionCount)
|
|
{
|
|
// Make sure memory is readable
|
|
if(!MemIsValidReadPtr(Start))
|
|
return false;
|
|
|
|
// Fail if boundary exceeds module size
|
|
auto moduleBase = ModBaseFromAddr(Start);
|
|
|
|
if(moduleBase != ModBaseFromAddr(End))
|
|
return false;
|
|
|
|
// Fail if 'Start' and 'End' are incompatible
|
|
if(Start > End || ArgumentOverlaps(Start, End))
|
|
return false;
|
|
|
|
ARGUMENTSINFO argument;
|
|
if(!ModNameFromAddr(Start, argument.mod, true))
|
|
*argument.mod = '\0';
|
|
argument.start = Start - moduleBase;
|
|
argument.end = End - moduleBase;
|
|
argument.manual = Manual;
|
|
argument.instructioncount = InstructionCount;
|
|
|
|
return arguments.Add(argument);
|
|
}
|
|
|
|
bool ArgumentGet(duint Address, duint* Start, duint* End, duint* InstrCount)
|
|
{
|
|
ARGUMENTSINFO argument;
|
|
if(!arguments.Get(Arguments::VaKey(Address, Address), argument))
|
|
return false;
|
|
arguments.AdjustValue(argument);
|
|
if(Start)
|
|
*Start = argument.start;
|
|
if(End)
|
|
*End = argument.end;
|
|
if(InstrCount)
|
|
*InstrCount = argument.instructioncount;
|
|
return true;
|
|
}
|
|
|
|
bool ArgumentOverlaps(duint Start, duint End)
|
|
{
|
|
// A argument can't end before it begins
|
|
if(Start > End)
|
|
return false;
|
|
return arguments.Contains(Arguments::VaKey(Start, End));
|
|
}
|
|
|
|
bool ArgumentDelete(duint Address)
|
|
{
|
|
return arguments.Delete(Arguments::VaKey(Address, Address));
|
|
}
|
|
|
|
void ArgumentDelRange(duint Start, duint End, bool DeleteManual)
|
|
{
|
|
// Should all arguments be deleted?
|
|
// 0x00000000 - 0xFFFFFFFF
|
|
if(Start == 0 && End == ~0)
|
|
{
|
|
ArgumentClear();
|
|
}
|
|
else
|
|
{
|
|
// The start and end address must be in the same module
|
|
auto moduleBase = ModBaseFromAddr(Start);
|
|
|
|
if(moduleBase != ModBaseFromAddr(End))
|
|
return;
|
|
|
|
// Convert these to a relative offset
|
|
Start -= moduleBase;
|
|
End -= moduleBase;
|
|
|
|
arguments.DeleteWhere([ = ](const ARGUMENTSINFO & value)
|
|
{
|
|
if(!DeleteManual && value.manual)
|
|
return false;
|
|
return value.end >= Start && value.start <= End;
|
|
});
|
|
}
|
|
}
|
|
|
|
void ArgumentCacheSave(JSON Root)
|
|
{
|
|
arguments.CacheSave(Root);
|
|
}
|
|
|
|
void ArgumentCacheLoad(JSON Root)
|
|
{
|
|
arguments.CacheLoad(Root);
|
|
}
|
|
|
|
void ArgumentClear()
|
|
{
|
|
arguments.Clear();
|
|
}
|
|
|
|
void ArgumentGetList(std::vector<ARGUMENTSINFO> & list)
|
|
{
|
|
arguments.GetList(list);
|
|
}
|
|
|
|
bool ArgumentGetInfo(duint Address, ARGUMENTSINFO & info)
|
|
{
|
|
return arguments.Get(Arguments::VaKey(Address, Address), info);
|
|
}
|