// Get the start/end of a loop at a certain depth and address bool LoopGet(int Depth, duint Address, duint* Start, duint* End) { ASSERT_DEBUGGING("Export call"); // Get the virtual address module const duint moduleBase = ModBaseFromAddr(Address); // Virtual address to relative address Address -= moduleBase; SHARED_ACQUIRE(LockLoops); // Search with this address range auto found = loops.find(DepthModuleRange(Depth, ModuleRange(ModHashFromAddr(moduleBase), Range(Address, Address)))); if(found == loops.end()) return false; // Return the loop start and end if(Start) *Start = found->second.start + moduleBase; if(End) *End = found->second.end + moduleBase; return true; }
bool FunctionAdd(uint Start, uint End, bool Manual) { // CHECK: Export/Command function if(!DbgIsDebugging()) return false; // Make sure memory is readable if(!MemIsValidReadPtr(Start)) return false; // Fail if boundary exceeds module size const uint 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; ModNameFromAddr(Start, function.mod, true); function.start = Start - moduleBase; function.end = End - moduleBase; function.manual = Manual; // Insert to global table EXCLUSIVE_ACQUIRE(LockFunctions); functions.insert(std::make_pair(ModuleRange(ModHashFromAddr(moduleBase), Range(function.start, function.end)), function)); return true; }
bool FunctionGet(uint Address, uint* Start, uint* End) { // CHECK: Exported function if(!DbgIsDebugging()) return false; const uint moduleBase = ModBaseFromAddr(Address); // Lookup by module hash, then function range SHARED_ACQUIRE(LockFunctions); auto found = functions.find(ModuleRange(ModHashFromAddr(moduleBase), Range(Address - moduleBase, Address - moduleBase))); // Was this range found? if(found == functions.end()) return false; if(Start) *Start = found->second.start + moduleBase; if(End) *End = found->second.end + moduleBase; return true; }
// Get the start/end of a loop at a certain depth and address bool LoopGet(int Depth, uint Address, uint* Start, uint* End) { // CHECK: Exported function if(!DbgIsDebugging()) return false; // Get the virtual address module const uint moduleBase = ModBaseFromAddr(Address); // Virtual address to relative address Address -= moduleBase; SHARED_ACQUIRE(LockLoops); // Search with this address range auto found = loops.find(DepthModuleRange(Depth, ModuleRange(ModHashFromAddr(moduleBase), Range(Address, Address)))); if(found == loops.end()) return false; // Return the loop start if(Start) *Start = found->second.start + moduleBase; // Also the loop end if(End) *End = found->second.end + moduleBase; return true; }
bool FunctionDelete(uint Address) { // CHECK: Exported function if(!DbgIsDebugging()) return false; const uint moduleBase = ModBaseFromAddr(Address); EXCLUSIVE_ACQUIRE(LockFunctions); return (functions.erase(ModuleRange(ModHashFromAddr(moduleBase), Range(Address - moduleBase, Address - moduleBase))) > 0); }
bool FunctionOverlaps(uint Start, uint End) { // CHECK: Exported function if(!DbgIsDebugging()) return false; // A function can't end before it begins if(Start > End) return false; const uint moduleBase = ModBaseFromAddr(Start); SHARED_ACQUIRE(LockFunctions); return (functions.count(ModuleRange(ModHashFromAddr(moduleBase), Range(Start - moduleBase, End - moduleBase))) > 0); }
bool LoopAdd(uint Start, uint End, bool Manual) { // CHECK: Export function if(!DbgIsDebugging()) return false; // Loop must begin before it ends if(Start > End) return false; // Memory addresses must be valid if(!MemIsValidReadPtr(Start) || !MemIsValidReadPtr(End)) return false; // Check if loop boundaries are in the same module range const uint moduleBase = ModBaseFromAddr(Start); if(moduleBase != ModBaseFromAddr(End)) return false; // Loops cannot overlap other loops int finalDepth = 0; if(LoopOverlaps(0, Start, End, &finalDepth)) return false; // Fill out loop information structure LOOPSINFO loopInfo; loopInfo.start = Start - moduleBase; loopInfo.end = End - moduleBase; loopInfo.depth = finalDepth; loopInfo.manual = Manual; ModNameFromAddr(Start, loopInfo.mod, true); // Link this to a parent loop if one does exist if(finalDepth) LoopGet(finalDepth - 1, Start, &loopInfo.parent, 0); else loopInfo.parent = 0; EXCLUSIVE_ACQUIRE(LockLoops); // Insert into list loops.insert(std::make_pair(DepthModuleRange(finalDepth, ModuleRange(ModHashFromAddr(moduleBase), Range(loopInfo.start, loopInfo.end))), loopInfo)); return true; }
void FunctionCacheLoad(JSON Root) { EXCLUSIVE_ACQUIRE(LockFunctions); // Delete existing entries functions.clear(); // Inline lambda to enumerate all JSON array indices auto InsertFunctions = [](const JSON Object, bool Manual) { size_t i; JSON value; json_array_foreach(Object, i, value) { FUNCTIONSINFO functionInfo; memset(&functionInfo, 0, sizeof(FUNCTIONSINFO)); // Copy module name const char* mod = json_string_value(json_object_get(value, "module")); if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE) strcpy_s(functionInfo.mod, mod); // Function address functionInfo.start = (uint)json_hex_value(json_object_get(value, "start")); functionInfo.end = (uint)json_hex_value(json_object_get(value, "end")); functionInfo.manual = Manual; // Sanity check if(functionInfo.end < functionInfo.start) continue; const uint key = ModHashFromName(functionInfo.mod); functions.insert(std::make_pair(ModuleRange(key, Range(functionInfo.start, functionInfo.end)), functionInfo)); } };
void LoopCacheLoad(JSON Root) { EXCLUSIVE_ACQUIRE(LockLoops); // Inline lambda to parse each JSON entry auto AddLoops = [](const JSON Object, bool Manual) { size_t i; JSON value; json_array_foreach(Object, i, value) { LOOPSINFO loopInfo; memset(&loopInfo, 0, sizeof(LOOPSINFO)); // Module name const char* mod = json_string_value(json_object_get(value, "module")); if(mod && strlen(mod) < MAX_MODULE_SIZE) strcpy_s(loopInfo.mod, mod); // All other variables loopInfo.start = (duint)json_hex_value(json_object_get(value, "start")); loopInfo.end = (duint)json_hex_value(json_object_get(value, "end")); loopInfo.depth = (int)json_integer_value(json_object_get(value, "depth")); loopInfo.parent = (duint)json_hex_value(json_object_get(value, "parent")); loopInfo.manual = Manual; // Sanity check: Make sure the loop starts before it ends if(loopInfo.end < loopInfo.start) continue; // Insert into global list loops.insert(std::make_pair(DepthModuleRange(loopInfo.depth, ModuleRange(ModHashFromName(loopInfo.mod), Range(loopInfo.start, loopInfo.end))), loopInfo)); } };
ModuleRange makeKey(const ARGUMENTSINFO & value) const override { return ModuleRange(ModHashFromName(value.mod), Range(value.start, value.end)); }