168 lines
4.2 KiB
C++
168 lines
4.2 KiB
C++
#include "function.h"
|
|
#include "module.h"
|
|
#include "memory.h"
|
|
#include "threading.h"
|
|
|
|
struct FunctionSerializer : JSONWrapper<FUNCTIONSINFO>
|
|
{
|
|
bool Save(const FUNCTIONSINFO & 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(FUNCTIONSINFO & value) override
|
|
{
|
|
//legacy support
|
|
value.manual = true;
|
|
getBool("manual", value.manual);
|
|
return getString("module", value.mod) &&
|
|
getHex("start", value.start) &&
|
|
getHex("end", value.end) &&
|
|
getHex("icount", value.instructioncount) &&
|
|
value.end >= value.start;
|
|
}
|
|
};
|
|
|
|
struct Functions : SerializableModuleRangeMap<LockFunctions, FUNCTIONSINFO, FunctionSerializer>
|
|
{
|
|
void AdjustValue(FUNCTIONSINFO & value) const override
|
|
{
|
|
auto base = ModBaseFromName(value.mod);
|
|
value.start += base;
|
|
value.end += base;
|
|
}
|
|
|
|
protected:
|
|
const char* jsonKey() const override
|
|
{
|
|
return "functions";
|
|
}
|
|
|
|
ModuleRange makeKey(const FUNCTIONSINFO & value) const override
|
|
{
|
|
return ModuleRange(ModHashFromName(value.mod), Range(value.start, value.end));
|
|
}
|
|
};
|
|
|
|
static Functions functions;
|
|
|
|
bool FunctionAdd(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 || FunctionOverlaps(Start, End))
|
|
return false;
|
|
|
|
FUNCTIONSINFO function;
|
|
if(!ModNameFromAddr(Start, function.mod, true))
|
|
*function.mod = '\0';
|
|
function.start = Start - moduleBase;
|
|
function.end = End - moduleBase;
|
|
function.manual = Manual;
|
|
function.instructioncount = InstructionCount;
|
|
|
|
return functions.Add(function);
|
|
}
|
|
|
|
bool FunctionGet(duint Address, duint* Start, duint* End, duint* InstrCount)
|
|
{
|
|
FUNCTIONSINFO function;
|
|
if(!functions.Get(Functions::VaKey(Address, Address), function))
|
|
return false;
|
|
functions.AdjustValue(function);
|
|
if(Start)
|
|
*Start = function.start;
|
|
if(End)
|
|
*End = function.end;
|
|
if(InstrCount)
|
|
*InstrCount = function.instructioncount;
|
|
return true;
|
|
}
|
|
|
|
bool FunctionOverlaps(duint Start, duint End)
|
|
{
|
|
// A function can't end before it begins
|
|
if(Start > End)
|
|
return false;
|
|
return functions.Contains(Functions::VaKey(Start, End));
|
|
}
|
|
|
|
bool FunctionDelete(duint Address)
|
|
{
|
|
return functions.Delete(Functions::VaKey(Address, Address));
|
|
}
|
|
|
|
void FunctionDelRange(duint Start, duint End, bool DeleteManual)
|
|
{
|
|
// Should all functions be deleted?
|
|
// 0x00000000 - 0xFFFFFFFF
|
|
if(Start == 0 && End == ~0)
|
|
{
|
|
FunctionClear();
|
|
}
|
|
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;
|
|
|
|
functions.DeleteWhere([ = ](const FUNCTIONSINFO & value)
|
|
{
|
|
if(!DeleteManual && value.manual)
|
|
return false;
|
|
return value.end >= Start && value.start <= End;
|
|
});
|
|
}
|
|
}
|
|
|
|
void FunctionCacheSave(JSON Root)
|
|
{
|
|
functions.CacheSave(Root);
|
|
}
|
|
|
|
void FunctionCacheLoad(JSON Root)
|
|
{
|
|
functions.CacheLoad(Root);
|
|
functions.CacheLoad(Root, "auto"); //legacy support
|
|
}
|
|
|
|
bool FunctionEnum(FUNCTIONSINFO* List, size_t* Size)
|
|
{
|
|
return functions.Enum(List, Size);
|
|
}
|
|
|
|
void FunctionClear()
|
|
{
|
|
functions.Clear();
|
|
}
|
|
|
|
void FunctionGetList(std::vector<FUNCTIONSINFO> & list)
|
|
{
|
|
functions.GetList(list);
|
|
}
|
|
|
|
bool FunctionGetInfo(duint Address, FUNCTIONSINFO & info)
|
|
{
|
|
return functions.Get(Functions::VaKey(Address, Address), info);
|
|
}
|