1
0
Fork 0

Finish label refactor

This commit is contained in:
Nukem 2015-04-04 21:48:12 -04:00
parent fad13af628
commit f2edbfa95a
5 changed files with 417 additions and 400 deletions

View File

@ -57,7 +57,7 @@ void BookmarkDelRange(uint Start, uint End)
return;
// Are all bookmarks going to be deleted?
// 0x00000000 - 0xFFFFFFFF
// 0x00000000 - 0xFFFFFFFF
if(Start == 0 && End == ~0)
{
EXCLUSIVE_ACQUIRE(LockBookmarks);
@ -143,8 +143,10 @@ void BookmarkCacheLoad(JSON Root)
// Load the module name
const char* mod = json_string_value(json_object_get(value, "module"));
if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE)
if(mod && strlen(mod) < MAX_MODULE_SIZE)
strcpy_s(bookmarkInfo.mod, mod);
else
bookmarkInfo.mod[0] = '\0';
// Load address and set auto-generated flag
bookmarkInfo.addr = (uint)json_hex_value(json_object_get(value, "address"));

View File

@ -80,7 +80,7 @@ void CommentDelRange(uint Start, uint End)
return;
// Are all comments going to be deleted?
// 0x00000000 - 0xFFFFFFFF
// 0x00000000 - 0xFFFFFFFF
if(Start == 0 && End == ~0)
{
EXCLUSIVE_ACQUIRE(LockComments);
@ -163,12 +163,12 @@ void CommentCacheLoad(JSON Root)
json_array_foreach(Object, i, value)
{
COMMENTSINFO commentInfo;
memset(&commentInfo, 0, sizeof(COMMENTSINFO));
memset(&commentInfo, 0, sizeof(COMMENTSINFO));
// Module
const char* mod = json_string_value(json_object_get(value, "module"));
if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE)
if(mod && strlen(mod) < MAX_MODULE_SIZE)
strcpy_s(commentInfo.mod, mod);
else
commentInfo.mod[0] = '\0';

View File

@ -8,37 +8,37 @@ std::unordered_map<uint, LABELSINFO> labels;
bool LabelSet(uint Address, const char* Text, bool Manual)
{
// CHECK: Exported/Command function
if (!DbgIsDebugging())
return false;
// CHECK: Exported/Command function
if (!DbgIsDebugging())
return false;
// A valid memory address must be supplied
if (!MemIsValidReadPtr(Address))
return false;
// A valid memory address must be supplied
if (!MemIsValidReadPtr(Address))
return false;
// Make sure the string is supplied, within bounds, and not a special delimiter
if (!Text || Text[0] == '\1' || strlen(Text) >= MAX_LABEL_SIZE - 1)
return false;
// Make sure the string is supplied, within bounds, and not a special delimiter
if (!Text || Text[0] == '\1' || strlen(Text) >= MAX_LABEL_SIZE - 1)
return false;
// Labels cannot be "address" of actual variables
if (strstr(Text, "&"))
return false;
// Labels cannot be "address" of actual variables
if (strstr(Text, "&"))
return false;
// Delete the label if no text was supplied
// Delete the label if no text was supplied
if(Text[0] == '\0')
return LabelDelete(Address);
// Fill out the structure data
// Fill out the structure data
LABELSINFO labelInfo;
labelInfo.manual = Manual;
labelInfo.addr = Address - ModBaseFromAddr(Address);
strcpy_s(labelInfo.text, Text);
labelInfo.manual = Manual;
labelInfo.addr = Address - ModBaseFromAddr(Address);
strcpy_s(labelInfo.text, Text);
ModNameFromAddr(Address, labelInfo.mod, true);
EXCLUSIVE_ACQUIRE(LockLabels);
EXCLUSIVE_ACQUIRE(LockLabels);
// Insert label by key
const uint key = ModHashFromAddr(Address);
// Insert label by key
const uint key = ModHashFromAddr(Address);
if(!labels.insert(std::make_pair(ModHashFromAddr(key), labelInfo)).second)
labels[key] = labelInfo;
@ -48,43 +48,43 @@ bool LabelSet(uint Address, const char* Text, bool Manual)
bool LabelFromString(const char* Text, uint* Address)
{
// CHECK: Future? (Not used)
// CHECK: Future? (Not used)
if(!DbgIsDebugging())
return false;
SHARED_ACQUIRE(LockLabels);
SHARED_ACQUIRE(LockLabels);
for (auto& itr : labels)
{
// Check if the actual label name matches
if (strcmp(itr.second.text, Text))
continue;
for (auto& itr : labels)
{
// Check if the actual label name matches
if (strcmp(itr.second.text, Text))
continue;
if (Address)
*Address = itr.second.addr + ModBaseFromName(itr.second.mod);
if (Address)
*Address = itr.second.addr + ModBaseFromName(itr.second.mod);
// Set status to indicate if label was ever found
return true;
}
// Set status to indicate if label was ever found
return true;
}
return false;
}
bool LabelGet(uint Address, char* Text)
{
// CHECK: Export function
// CHECK: Export function
if(!DbgIsDebugging())
return false;
SHARED_ACQUIRE(LockLabels);
SHARED_ACQUIRE(LockLabels);
// Was the label at this address exist?
auto found = labels.find(ModHashFromAddr(Address));
// Was the label at this address exist?
auto found = labels.find(ModHashFromAddr(Address));
if(found == labels.end())
return false;
// Copy to user buffer
// Copy to user buffer
if(Text)
strcpy_s(Text, MAX_LABEL_SIZE, found->second.text);
@ -93,63 +93,63 @@ bool LabelGet(uint Address, char* Text)
bool LabelDelete(uint Address)
{
// CHECK: Export function
// CHECK: Export function
if(!DbgIsDebugging())
return false;
EXCLUSIVE_ACQUIRE(LockLabels);
EXCLUSIVE_ACQUIRE(LockLabels);
return (labels.erase(ModHashFromAddr(Address)) > 0);
}
void LabelDelRange(uint Start, uint End)
{
// CHECK: Export function
if (!DbgIsDebugging())
return;
// CHECK: Export function
if (!DbgIsDebugging())
return;
// Are all comments going to be deleted?
// 0x00000000 - 0xFFFFFFFF
if (Start == 0 && End == ~0)
{
EXCLUSIVE_ACQUIRE(LockLabels);
labels.clear();
}
else
{
// Make sure 'Start' and 'End' reference the same module
uint moduleBase = ModBaseFromAddr(Start);
// Are all comments going to be deleted?
// 0x00000000 - 0xFFFFFFFF
if (Start == 0 && End == ~0)
{
EXCLUSIVE_ACQUIRE(LockLabels);
labels.clear();
}
else
{
// Make sure 'Start' and 'End' reference the same module
uint moduleBase = ModBaseFromAddr(Start);
if (moduleBase != ModBaseFromAddr(End))
return;
if (moduleBase != ModBaseFromAddr(End))
return;
EXCLUSIVE_ACQUIRE(LockLabels);
for (auto itr = labels.begin(); itr != labels.end();)
{
// Ignore manually set entries
if (itr->second.manual)
{
itr++;
continue;
}
EXCLUSIVE_ACQUIRE(LockLabels);
for (auto itr = labels.begin(); itr != labels.end();)
{
// Ignore manually set entries
if (itr->second.manual)
{
itr++;
continue;
}
// [Start, End)
if (itr->second.addr >= Start && itr->second.addr < End)
itr = labels.erase(itr);
else
itr++;
}
}
// [Start, End)
if (itr->second.addr >= Start && itr->second.addr < End)
itr = labels.erase(itr);
else
itr++;
}
}
}
void LabelCacheSave(JSON Root)
{
EXCLUSIVE_ACQUIRE(LockLabels);
EXCLUSIVE_ACQUIRE(LockLabels);
// Create the sub-root structures in memory
const JSON jsonLabels = json_array();
const JSON jsonAutoLabels = json_array();
// Create the sub-root structures in memory
const JSON jsonLabels = json_array();
const JSON jsonAutoLabels = json_array();
// Iterator each label
// Iterator each label
for(auto& itr : labels)
{
JSON jsonLabel = json_object();
@ -157,126 +157,126 @@ void LabelCacheSave(JSON Root)
json_object_set_new(jsonLabel, "address", json_hex(itr.second.addr));
json_object_set_new(jsonLabel, "text", json_string(itr.second.text));
// Was the label manually added?
// Was the label manually added?
if(itr.second.manual)
json_array_append_new(jsonLabels, jsonLabel);
else
json_array_append_new(jsonAutoLabels, jsonLabel);
}
// Apply the object to the global root
// Apply the object to the global root
if(json_array_size(jsonLabels))
json_object_set(Root, "labels", jsonLabels);
if(json_array_size(jsonAutoLabels))
json_object_set(Root, "autolabels", jsonAutoLabels);
json_decref(jsonLabels);
json_decref(jsonAutoLabels);
json_decref(jsonLabels);
json_decref(jsonAutoLabels);
}
void LabelCacheLoad(JSON Root)
{
EXCLUSIVE_ACQUIRE(LockLabels);
EXCLUSIVE_ACQUIRE(LockLabels);
// Inline lambda to parse each JSON entry
auto AddLabels = [](const JSON Object, bool Manual)
{
size_t i;
JSON value;
// Inline lambda to parse each JSON entry
auto AddLabels = [](const JSON Object, bool Manual)
{
size_t i;
JSON value;
json_array_foreach(Object, i, value)
{
LABELSINFO labelInfo;
memset(&labelInfo, 0, sizeof(LABELSINFO));
json_array_foreach(Object, i, value)
{
LABELSINFO labelInfo;
memset(&labelInfo, 0, sizeof(LABELSINFO));
// Module
const char* mod = json_string_value(json_object_get(value, "module"));
// Module
const char* mod = json_string_value(json_object_get(value, "module"));
if (mod && *mod && strlen(mod) < MAX_MODULE_SIZE)
strcpy_s(labelInfo.mod, mod);
else
labelInfo.mod[0] = '\0';
if (mod && strlen(mod) < MAX_MODULE_SIZE)
strcpy_s(labelInfo.mod, mod);
else
labelInfo.mod[0] = '\0';
// Address/Manual
labelInfo.addr = (uint)json_hex_value(json_object_get(value, "address"));
labelInfo.manual = Manual;
// Address/Manual
labelInfo.addr = (uint)json_hex_value(json_object_get(value, "address"));
labelInfo.manual = Manual;
// Text string
const char* text = json_string_value(json_object_get(value, "text"));
// Text string
const char* text = json_string_value(json_object_get(value, "text"));
if (text)
strcpy_s(labelInfo.text, text);
else
{
// Skip empty strings
continue;
}
// Go through the string replacing '&' with spaces
for (char *ptr = labelInfo.text; ptr[0] != '\0'; ptr++)
{
if (ptr[0] == '&')
ptr[0] = ' ';
}
if (text)
strcpy_s(labelInfo.text, text);
else
{
// Skip empty strings
continue;
}
// Finally insert the data
const uint key = ModHashFromName(labelInfo.mod) + labelInfo.addr;
// Go through the string replacing '&' with spaces
for (char *ptr = labelInfo.text; ptr[0] != '\0'; ptr++)
{
if (ptr[0] == '&')
ptr[0] = ' ';
}
labels.insert(std::make_pair(key, labelInfo));
}
};
// Finally insert the data
const uint key = ModHashFromName(labelInfo.mod) + labelInfo.addr;
// Remove previous data
labels.clear();
labels.insert(std::make_pair(key, labelInfo));
}
};
const JSON jsonLabels = json_object_get(Root, "labels");
const JSON jsonAutoLabels = json_object_get(Root, "autolabels");
// Remove previous data
labels.clear();
// Load user-set labels
if (jsonLabels)
AddLabels(jsonLabels, true);
const JSON jsonLabels = json_object_get(Root, "labels");
const JSON jsonAutoLabels = json_object_get(Root, "autolabels");
// Load auto-set labels
if (jsonAutoLabels)
AddLabels(jsonAutoLabels, false);
// Load user-set labels
if (jsonLabels)
AddLabels(jsonLabels, true);
// Load auto-set labels
if (jsonAutoLabels)
AddLabels(jsonAutoLabels, false);
}
bool LabelEnum(LABELSINFO* List, size_t* Size)
{
// CHECK: Export function
// CHECK: Export function
if(!DbgIsDebugging())
return false;
// At least 1 parameter is required
// At least 1 parameter is required
if(!List && !Size)
return false;
EXCLUSIVE_ACQUIRE(LockLabels);
EXCLUSIVE_ACQUIRE(LockLabels);
// See if the user requested a size
// See if the user requested a size
if(Size)
{
*Size = labels.size() * sizeof(LABELSINFO);
if (!List)
return true;
if (!List)
return true;
}
// Fill out the return list while converting the offset
// to a virtual address
for (auto& itr : labels)
{
*List = itr.second;
List->addr += ModBaseFromName(itr.second.mod);
List++;
}
// Fill out the return list while converting the offset
// to a virtual address
for (auto& itr : labels)
{
*List = itr.second;
List->addr += ModBaseFromName(itr.second.mod);
List++;
}
return true;
}
void LabelClear()
{
EXCLUSIVE_ACQUIRE(LockLabels);
labels.clear();
EXCLUSIVE_ACQUIRE(LockLabels);
labels.clear();
}

View File

@ -8,48 +8,47 @@ std::map<DepthModuleRange, LOOPSINFO, DepthModuleRangeCompare> loops;
bool LoopAdd(uint Start, uint End, bool Manual)
{
// CHECK: Export function
// CHECK: Export function
if(!DbgIsDebugging())
return false;
// Loop must begin before it ends
if (Start > End)
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;
// Memory addresses must be valid
if (!MemIsValidReadPtr(Start) || !MemIsValidReadPtr(End))
return false;
// Check if loop boundaries are in the same module range
// 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;
// Loops cannot overlap other loops
int finalDepth = 0;
if(LoopOverlaps(0, Start, End, &finalDepth))
return false;
// Fill out loop information structure
// Fill out loop information structure
LOOPSINFO loopInfo;
loopInfo.start = Start - moduleBase;
loopInfo.end = End - moduleBase;
loopInfo.depth = finalDepth;
loopInfo.manual = Manual;
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)
// 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);
EXCLUSIVE_ACQUIRE(LockLoops);
// Insert into list
// Insert into list
loops.insert(std::make_pair(DepthModuleRange(finalDepth, ModuleRange(ModHashFromAddr(moduleBase), Range(loopInfo.start, loopInfo.end))), loopInfo));
return true;
}
@ -57,29 +56,29 @@ bool LoopAdd(uint Start, uint End, bool Manual)
// 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
// CHECK: Exported function
if(!DbgIsDebugging())
return false;
// Get the virtual address module
// Get the virtual address module
const uint moduleBase = ModBaseFromAddr(Address);
// Virtual address to relative address
Address -= moduleBase;
// Virtual address to relative address
Address -= moduleBase;
SHARED_ACQUIRE(LockLoops);
SHARED_ACQUIRE(LockLoops);
// Search with this address range
// 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
// Return the loop start
if(Start)
*Start = found->second.start + moduleBase;
// Also the loop end
// Also the loop end
if(End)
*End = found->second.end + moduleBase;
@ -89,48 +88,48 @@ bool LoopGet(int Depth, uint Address, uint* Start, uint* End)
//check if a loop overlaps a range, inside is not overlapping
bool LoopOverlaps(int Depth, uint Start, uint End, int* FinalDepth)
{
// CHECK: Export function
// CHECK: Export function
if(!DbgIsDebugging())
return false;
// Determine module addresses and lookup keys
const uint moduleBase = ModBaseFromAddr(Start);
const uint key = ModHashFromAddr(moduleBase);
// Determine module addresses and lookup keys
const uint moduleBase = ModBaseFromAddr(Start);
const uint key = ModHashFromAddr(moduleBase);
uint curStart = Start - moduleBase;
uint curEnd = End - moduleBase;
uint curStart = Start - moduleBase;
uint curEnd = End - moduleBase;
SHARED_ACQUIRE(LockLoops);
SHARED_ACQUIRE(LockLoops);
// Check if the new loop fits in the old loop
for(auto& itr : loops)
{
// Only look in the current module
// Only look in the current module
if(itr.first.second.first != key)
continue;
// Loop must be at this recursive depth
if (itr.second.depth != Depth)
continue;
// Loop must be at this recursive depth
if (itr.second.depth != Depth)
continue;
if(itr.second.start < curStart && itr.second.end > curEnd)
return LoopOverlaps(Depth + 1, curStart, curEnd, FinalDepth);
}
// Did the user request t the loop depth?
// Did the user request t the loop depth?
if(FinalDepth)
*FinalDepth = Depth;
// Check for loop overlaps
for (auto& itr : loops)
for (auto& itr : loops)
{
// Only look in the current module
if (itr.first.second.first != key)
continue;
// Only look in the current module
if (itr.first.second.first != key)
continue;
// Loop must be at this recursive depth
if (itr.second.depth != Depth)
continue;
// Loop must be at this recursive depth
if (itr.second.depth != Depth)
continue;
if(itr.second.start <= curEnd && itr.second.end >= curStart)
return true;
@ -147,81 +146,94 @@ bool LoopDelete(int Depth, uint Address)
void LoopCacheSave(JSON Root)
{
EXCLUSIVE_ACQUIRE(LockLoops);
const JSON jsonloops = json_array();
const JSON jsonautoloops = json_array();
for(auto& itr : loops)
EXCLUSIVE_ACQUIRE(LockLoops);
// Create the root JSON objects
const JSON jsonLoops = json_array();
const JSON jsonAutoLoops = json_array();
// Write all entries
for(auto& itr : loops)
{
const LOOPSINFO curLoop = itr.second;
JSON curjsonloop = json_object();
json_object_set_new(curjsonloop, "module", json_string(curLoop.mod));
json_object_set_new(curjsonloop, "start", json_hex(curLoop.start));
json_object_set_new(curjsonloop, "end", json_hex(curLoop.end));
json_object_set_new(curjsonloop, "depth", json_integer(curLoop.depth));
json_object_set_new(curjsonloop, "parent", json_hex(curLoop.parent));
if(curLoop.manual)
json_array_append_new(jsonloops, curjsonloop);
const LOOPSINFO& currentLoop = itr.second;
JSON currentJson = json_object();
json_object_set_new(currentJson, "module", json_string(currentLoop.mod));
json_object_set_new(currentJson, "start", json_hex(currentLoop.start));
json_object_set_new(currentJson, "end", json_hex(currentLoop.end));
json_object_set_new(currentJson, "depth", json_integer(currentLoop.depth));
json_object_set_new(currentJson, "parent", json_hex(currentLoop.parent));
if(currentLoop.manual)
json_array_append_new(jsonLoops, currentJson);
else
json_array_append_new(jsonautoloops, curjsonloop);
json_array_append_new(jsonAutoLoops, currentJson);
}
if(json_array_size(jsonloops))
json_object_set(Root, "loops", jsonloops);
json_decref(jsonloops);
if(json_array_size(jsonautoloops))
json_object_set(Root, "autoloops", jsonautoloops);
json_decref(jsonautoloops);
// Append a link to the global root
if(json_array_size(jsonLoops))
json_object_set(Root, "loops", jsonLoops);
if(json_array_size(jsonAutoLoops))
json_object_set(Root, "autoloops", jsonAutoLoops);
// Release memory/references
json_decref(jsonLoops);
json_decref(jsonAutoLoops);
}
void LoopCacheLoad(JSON Root)
{
EXCLUSIVE_ACQUIRE(LockLoops);
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);
else
loopInfo.mod[0] = '\0';
// All other variables
loopInfo.start = (uint)json_hex_value(json_object_get(value, "start"));
loopInfo.end = (uint)json_hex_value(json_object_get(value, "end"));
loopInfo.depth = (int)json_integer_value(json_object_get(value, "depth"));
loopInfo.parent = (uint)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));
}
};
// Remove existing entries
loops.clear();
const JSON jsonloops = json_object_get(Root, "loops");
if(jsonloops)
{
size_t i;
JSON value;
json_array_foreach(jsonloops, i, value)
{
LOOPSINFO curLoop;
const char* mod = json_string_value(json_object_get(value, "module"));
if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE)
strcpy_s(curLoop.mod, mod);
else
*curLoop.mod = '\0';
curLoop.start = (uint)json_hex_value(json_object_get(value, "start"));
curLoop.end = (uint)json_hex_value(json_object_get(value, "end"));
curLoop.depth = (int)json_integer_value(json_object_get(value, "depth"));
curLoop.parent = (uint)json_hex_value(json_object_get(value, "parent"));
if(curLoop.end < curLoop.start)
continue; //invalid loop
curLoop.manual = true;
loops.insert(std::make_pair(DepthModuleRange(curLoop.depth, ModuleRange(ModHashFromName(curLoop.mod), Range(curLoop.start, curLoop.end))), curLoop));
}
}
JSON jsonautoloops = json_object_get(Root, "autoloops");
if(jsonautoloops)
{
size_t i;
JSON value;
json_array_foreach(jsonautoloops, i, value)
{
LOOPSINFO curLoop;
const char* mod = json_string_value(json_object_get(value, "module"));
if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE)
strcpy_s(curLoop.mod, mod);
else
*curLoop.mod = '\0';
curLoop.start = (uint)json_hex_value(json_object_get(value, "start"));
curLoop.end = (uint)json_hex_value(json_object_get(value, "end"));
curLoop.depth = (int)json_integer_value(json_object_get(value, "depth"));
curLoop.parent = (uint)json_hex_value(json_object_get(value, "parent"));
if(curLoop.end < curLoop.start)
continue; //invalid loop
curLoop.manual = false;
loops.insert(std::make_pair(DepthModuleRange(curLoop.depth, ModuleRange(ModHashFromName(curLoop.mod), Range(curLoop.start, curLoop.end))), curLoop));
}
}
const JSON jsonLoops = json_object_get(Root, "loops");
const JSON jsonAutoLoops = json_object_get(Root, "autoloops");
// Load user-set loops
if (jsonLoops)
AddLoops(jsonLoops, true);
// Load auto-set loops
if (jsonAutoLoops)
AddLoops(jsonAutoLoops, false);
}
bool LoopEnum(LOOPSINFO* List, size_t* Size)
@ -241,14 +253,14 @@ bool LoopEnum(LOOPSINFO* List, size_t* Size)
return true;
}
for (auto& itr : loops)
for (auto& itr : loops)
{
*List = itr.second;
// Adjust the offset to a real virtual address
uint modbase = ModBaseFromName(List->mod);
List->start += modbase;
List->end += modbase;
List->start += modbase;
List->end += modbase;
List++;
}

View File

@ -16,171 +16,174 @@ std::unordered_map<uint, PATCHINFO> patches;
bool PatchSet(uint Address, unsigned char OldByte, unsigned char NewByte)
{
// MemIsValidReadPtr also checks if the debugger is actually
// debugging
// CHECK: Exported function
if (!DbgIsDebugging())
return false;
// Address must be valid
if(!MemIsValidReadPtr(Address))
return false;
// Don't patch anything if the new and old values are the same
// Don't patch anything if the new and old values are the same
if(OldByte == NewByte)
return true;
PATCHINFO newPatch;
newPatch.addr = Address - ModBaseFromAddr(Address);
newPatch.oldbyte = OldByte;
newPatch.newbyte = NewByte;
ModNameFromAddr(Address, newPatch.mod, true);
newPatch.addr = Address - ModBaseFromAddr(Address);
newPatch.oldbyte = OldByte;
newPatch.newbyte = NewByte;
ModNameFromAddr(Address, newPatch.mod, true);
// Generate a key for this address
// Generate a key for this address
const uint key = ModHashFromAddr(Address);
EXCLUSIVE_ACQUIRE(LockPatches);
EXCLUSIVE_ACQUIRE(LockPatches);
// Find any patch with this specific address
// Find any patch with this specific address
auto found = patches.find(key);
if(found != patches.end())
{
if(found->second.oldbyte == NewByte)
{
// The patch was undone here
// The patch was undone here
patches.erase(found);
return true;
}
else
{
// Keep the original byte from the previous patch
newPatch.oldbyte = found->second.oldbyte;
found->second = newPatch;
// Keep the original byte from the previous patch
newPatch.oldbyte = found->second.oldbyte;
found->second = newPatch;
}
}
else
{
// The entry was never found, insert it
patches.insert(std::make_pair(key, newPatch));
}
else
{
// The entry was never found, insert it
patches.insert(std::make_pair(key, newPatch));
}
return true;
}
bool PatchGet(uint Address, PATCHINFO* Patch)
{
// CHECK: Export
// CHECK: Export
if(!DbgIsDebugging())
return false;
SHARED_ACQUIRE(LockPatches);
SHARED_ACQUIRE(LockPatches);
// Find this specific address in the list
// Find this specific address in the list
auto found = patches.find(ModHashFromAddr(Address));
if(found == patches.end())
return false;
// Did the user request an output buffer?
if(Patch)
// Did the user request an output buffer?
if(Patch)
{
*Patch = found->second;
*Patch = found->second;
Patch->addr += ModBaseFromAddr(Address);
}
// Return true because the patch was found
return true;
// Return true because the patch was found
return true;
}
bool PatchDelete(uint Address, bool Restore)
{
// CHECK: Export function
// CHECK: Export function
if(!DbgIsDebugging())
return false;
EXCLUSIVE_ACQUIRE(LockPatches);
EXCLUSIVE_ACQUIRE(LockPatches);
// Do a list lookup with hash
// Do a list lookup with hash
auto found = patches.find(ModHashFromAddr(Address));
if(found == patches.end())
return false;
// Restore the original byte at this address
if(Restore)
// Restore the original byte at this address
if(Restore)
MemWrite((void*)(found->second.addr + ModBaseFromAddr(Address)), &found->second.oldbyte, sizeof(char), nullptr);
// Finally remove it from the list
// Finally remove it from the list
patches.erase(found);
return true;
}
void PatchDelRange(uint Start, uint End, bool Restore)
{
// CHECK: Export call
if (!DbgIsDebugging())
return;
// CHECK: Export call
if (!DbgIsDebugging())
return;
// Are all bookmarks going to be deleted?
// 0x00000000 - 0xFFFFFFFF
if (Start == 0 && End == ~0)
{
EXCLUSIVE_ACQUIRE(LockPatches);
patches.clear();
}
else
{
// Make sure 'Start' and 'End' reference the same module
uint moduleBase = ModBaseFromAddr(Start);
// Are all bookmarks going to be deleted?
// 0x00000000 - 0xFFFFFFFF
if (Start == 0 && End == ~0)
{
EXCLUSIVE_ACQUIRE(LockPatches);
patches.clear();
}
else
{
// Make sure 'Start' and 'End' reference the same module
uint moduleBase = ModBaseFromAddr(Start);
if (moduleBase != ModBaseFromAddr(End))
return;
if (moduleBase != ModBaseFromAddr(End))
return;
// VA to RVA in module
Start -= moduleBase;
End -= moduleBase;
// VA to RVA in module
Start -= moduleBase;
End -= moduleBase;
EXCLUSIVE_ACQUIRE(LockPatches);
for (auto itr = patches.begin(); itr != patches.end();)
{
// [Start, End)
if (itr->second.addr >= Start && itr->second.addr < End)
{
// Restore the original byte if necessary
if (Restore)
MemWrite((void*)(itr->second.addr + moduleBase), &itr->second.oldbyte, sizeof(char), nullptr);
EXCLUSIVE_ACQUIRE(LockPatches);
for (auto itr = patches.begin(); itr != patches.end();)
{
// [Start, End)
if (itr->second.addr >= Start && itr->second.addr < End)
{
// Restore the original byte if necessary
if (Restore)
MemWrite((void*)(itr->second.addr + moduleBase), &itr->second.oldbyte, sizeof(char), nullptr);
itr = patches.erase(itr);
}
else
itr++;
}
}
itr = patches.erase(itr);
}
else
itr++;
}
}
}
bool PatchEnum(PATCHINFO* List, size_t* Size)
{
// CHECK: Exported
// CHECK: Exported
if(!DbgIsDebugging())
return false;
// At least one parameter is needed
// At least one parameter is needed
if(!List && !Size)
return false;
SHARED_ACQUIRE(LockPatches);
SHARED_ACQUIRE(LockPatches);
// Did the user request the size?
// Did the user request the size?
if(Size)
{
*Size = patches.size() * sizeof(PATCHINFO);
if (!List)
return true;
if (!List)
return true;
}
// Copy each vector entry to a C-style array
// Copy each vector entry to a C-style array
for(auto& itr : patches)
{
*List = itr.second;
List->addr += ModBaseFromName(itr.second.mod);;
List++;
*List = itr.second;
List->addr += ModBaseFromName(itr.second.mod);;
List++;
}
return true;
@ -188,36 +191,36 @@ bool PatchEnum(PATCHINFO* List, size_t* Size)
int PatchFile(const PATCHINFO* List, int Count, const char* FileName, char* Error)
{
//
// This function returns an int based on the number
// of patches applied. -1 indicates a failure.
//
//
// This function returns an int based on the number
// of patches applied. -1 indicates a failure.
//
if(Count <= 0)
{
// Notify the user of the error
// Notify the user of the error
if(Error)
strcpy_s(Error, MAX_ERROR_SIZE, "No patches to apply");
return -1;
}
// Get a copy of the first module name in the array
// Get a copy of the first module name in the array
char moduleName[MAX_MODULE_SIZE];
strcpy_s(moduleName, List[0].mod);
// Check if all patches are in the same module
for (int i = 0; i < Count; i++)
{
if (_stricmp(List[i].mod, moduleName))
{
if (Error)
sprintf_s(Error, MAX_ERROR_SIZE, "not all patches are in module %s", moduleName);
for (int i = 0; i < Count; i++)
{
if (_stricmp(List[i].mod, moduleName))
{
if (Error)
sprintf_s(Error, MAX_ERROR_SIZE, "not all patches are in module %s", moduleName);
return -1;
}
}
return -1;
}
}
// See if the module was loaded
// See if the module was loaded
uint moduleBase = ModBaseFromName(moduleName);
if(!moduleBase)
@ -227,9 +230,9 @@ int PatchFile(const PATCHINFO* List, int Count, const char* FileName, char* Erro
return -1;
}
// Get the unicode version of the module's path
wchar_t originalName[MAX_PATH];
// Get the unicode version of the module's path
wchar_t originalName[MAX_PATH];
if(!GetModuleFileNameExW(fdProcessInfo->hProcess, (HMODULE)moduleBase, originalName, ARRAYSIZE(originalName)))
{
@ -239,7 +242,7 @@ int PatchFile(const PATCHINFO* List, int Count, const char* FileName, char* Erro
return -1;
}
// Create a temporary backup file
// Create a temporary backup file
if(!CopyFileW(originalName, StringUtils::Utf8ToUtf16(FileName).c_str(), false))
{
if(Error)
@ -252,21 +255,21 @@ int PatchFile(const PATCHINFO* List, int Count, const char* FileName, char* Erro
DWORD loadedSize;
HANDLE fileMap;
ULONG_PTR fileMapVa;
if (!StaticFileLoadW(StringUtils::Utf8ToUtf16(FileName).c_str(), UE_ACCESS_ALL, false, &fileHandle, &loadedSize, &fileMap, &fileMapVa))
{
strcpy_s(Error, MAX_ERROR_SIZE, "StaticFileLoad failed");
return -1;
}
if (!StaticFileLoadW(StringUtils::Utf8ToUtf16(FileName).c_str(), UE_ACCESS_ALL, false, &fileHandle, &loadedSize, &fileMap, &fileMapVa))
{
strcpy_s(Error, MAX_ERROR_SIZE, "StaticFileLoad failed");
return -1;
}
// Begin iterating all patches, applying them to a file
// Begin iterating all patches, applying them to a file
int patchCount = 0;
for(int i = 0; i < Count; i++)
{
// Convert the virtual address to an offset within disk file data
// Convert the virtual address to an offset within disk file data
unsigned char* ptr = (unsigned char*)ConvertVAtoFileOffsetEx(fileMapVa, loadedSize, moduleBase, List[i].addr, false, true);
// Skip patches that do not have a raw address
// Skip patches that do not have a raw address
if(!ptr)
continue;
@ -275,7 +278,7 @@ int PatchFile(const PATCHINFO* List, int Count, const char* FileName, char* Erro
patchCount++;
}
// Unload the file from memory and commit changes to disk
// Unload the file from memory and commit changes to disk
if(!StaticFileUnloadW(StringUtils::Utf8ToUtf16(FileName).c_str(), true, fileHandle, loadedSize, fileMap, fileMapVa))
{
if(Error)
@ -284,33 +287,33 @@ int PatchFile(const PATCHINFO* List, int Count, const char* FileName, char* Erro
return -1;
}
// Zero the error message and return count
if (Error)
memset(Error, 0, MAX_ERROR_SIZE * sizeof(char));
// Zero the error message and return count
if (Error)
memset(Error, 0, MAX_ERROR_SIZE * sizeof(char));
return patchCount;
}
void PatchClear(const char* Module)
{
EXCLUSIVE_ACQUIRE(LockPatches);
EXCLUSIVE_ACQUIRE(LockPatches);
// Was a module specified?
if (!Module || Module[0] == '\0')
{
// No specific entries to delete, so remove all of them
patches.clear();
}
else
{
// Otherwise iterate over each patch and check the owner
// module for the address
for (auto itr = patches.begin(); itr != patches.end();)
{
if (!_stricmp(itr->second.mod, Module))
itr = patches.erase(itr);
else
itr++;
}
}
// Was a module specified?
if (!Module || Module[0] == '\0')
{
// No specific entries to delete, so remove all of them
patches.clear();
}
else
{
// Otherwise iterate over each patch and check the owner
// module for the address
for (auto itr = patches.begin(); itr != patches.end();)
{
if (!_stricmp(itr->second.mod, Module))
itr = patches.erase(itr);
else
itr++;
}
}
}