1
0
Fork 0
x64dbg/x64_dbg_dbg/label.cpp

281 lines
7.1 KiB
C++

#include "label.h"
#include "threading.h"
#include "module.h"
#include "memory.h"
std::unordered_map<uint, LABELSINFO> labels;
bool LabelSet(uint Address, const char* Text, bool Manual)
{
// CHECK: Exported/Command function
if(!DbgIsDebugging())
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;
// Labels cannot be "address" of actual variables
if(strstr(Text, "&"))
return false;
// Delete the label if no text was supplied
if(Text[0] == '\0')
return LabelDelete(Address);
// Fill out the structure data
LABELSINFO labelInfo;
labelInfo.manual = Manual;
labelInfo.addr = Address - ModBaseFromAddr(Address);
strcpy_s(labelInfo.text, Text);
ModNameFromAddr(Address, labelInfo.mod, true);
EXCLUSIVE_ACQUIRE(LockLabels);
// Insert label by key
const uint key = ModHashFromAddr(Address);
if(!labels.insert(std::make_pair(ModHashFromAddr(key), labelInfo)).second)
labels[key] = labelInfo;
return true;
}
bool LabelFromString(const char* Text, uint* Address)
{
// CHECK: Future? (Not used)
if(!DbgIsDebugging())
return false;
SHARED_ACQUIRE(LockLabels);
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);
// Set status to indicate if label was ever found
return true;
}
return false;
}
bool LabelGet(uint Address, char* Text)
{
// CHECK: Export function
if(!DbgIsDebugging())
return false;
SHARED_ACQUIRE(LockLabels);
// Was the label at this address exist?
auto found = labels.find(ModHashFromAddr(Address));
if(found == labels.end())
return false;
// Copy to user buffer
if(Text)
strcpy_s(Text, MAX_LABEL_SIZE, found->second.text);
return true;
}
bool LabelDelete(uint Address)
{
// CHECK: Export function
if(!DbgIsDebugging())
return false;
EXCLUSIVE_ACQUIRE(LockLabels);
return (labels.erase(ModHashFromAddr(Address)) > 0);
}
void LabelDelRange(uint Start, uint End)
{
// CHECK: Export function
if(!DbgIsDebugging())
return;
// Are all comments going to be deleted?
// 0x00000000 - 0xFFFFFFFF
if(Start == 0 && End == ~0)
{
LabelClear();
}
else
{
// Make sure 'Start' and 'End' reference the same module
uint moduleBase = ModBaseFromAddr(Start);
if(moduleBase != ModBaseFromAddr(End))
return;
EXCLUSIVE_ACQUIRE(LockLabels);
for(auto itr = labels.begin(); itr != labels.end();)
{
const auto & currentLabel = itr->second;
// Ignore manually set entries
if(currentLabel.manual)
{
++itr;
continue;
}
// [Start, End)
if(currentLabel.addr >= Start && currentLabel.addr < End)
itr = labels.erase(itr);
else
++itr;
}
}
}
void LabelCacheSave(JSON Root)
{
EXCLUSIVE_ACQUIRE(LockLabels);
// Create the sub-root structures in memory
const JSON jsonLabels = json_array();
const JSON jsonAutoLabels = json_array();
// Iterator each label
for(auto & itr : labels)
{
JSON jsonLabel = json_object();
json_object_set_new(jsonLabel, "module", json_string(itr.second.mod));
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?
if(itr.second.manual)
json_array_append_new(jsonLabels, jsonLabel);
else
json_array_append_new(jsonAutoLabels, jsonLabel);
}
// 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);
}
void LabelCacheLoad(JSON Root)
{
EXCLUSIVE_ACQUIRE(LockLabels);
// 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));
// Module
const char* mod = json_string_value(json_object_get(value, "module"));
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;
// 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] = ' ';
}
// Finally insert the data
const uint key = ModHashFromName(labelInfo.mod) + labelInfo.addr;
labels.insert(std::make_pair(key, labelInfo));
}
};
// Remove previous data
labels.clear();
const JSON jsonLabels = json_object_get(Root, "labels");
const JSON jsonAutoLabels = json_object_get(Root, "autolabels");
// 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
if(!DbgIsDebugging())
return false;
// At least 1 parameter is required
if(!List && !Size)
return false;
EXCLUSIVE_ACQUIRE(LockLabels);
// See if the user requested a size
if(Size)
{
*Size = labels.size() * sizeof(LABELSINFO);
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++;
}
return true;
}
void LabelClear()
{
EXCLUSIVE_ACQUIRE(LockLabels);
labels.clear();
}