1
0
Fork 0

Refactor function.cpp/.h

This commit is contained in:
Nukem 2015-03-18 19:03:18 -04:00
parent 003babb4bb
commit 0abe4fc1bd
8 changed files with 236 additions and 172 deletions

View File

@ -138,12 +138,12 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDR
}
if(addrinfo->flags & flagbookmark)
{
addrinfo->isbookmark = bookmarkget(addr);
addrinfo->isbookmark = BookmarkGet(addr);
retval = true;
}
if(addrinfo->flags & flagfunction)
{
if(functionget(addr, &addrinfo->function.start, &addrinfo->function.end))
if(FunctionGet(addr, &addrinfo->function.start, &addrinfo->function.end))
retval = true;
}
if(addrinfo->flags & flagloop)
@ -306,9 +306,9 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoset(duint addr, ADDRINFO* addrinfo)
if(addrinfo->flags & flagbookmark) //set bookmark
{
if(addrinfo->isbookmark)
retval = bookmarkset(addr, true);
retval = BookmarkSet(addr, true);
else
retval = bookmarkdel(addr);
retval = BookmarkDelete(addr);
}
return retval;
}
@ -614,7 +614,7 @@ extern "C" DLL_EXPORT uint _dbg_getbranchdestination(uint addr)
extern "C" DLL_EXPORT bool _dbg_functionoverlaps(uint start, uint end)
{
return functionoverlaps(start, end);
return FunctionOverlaps(start, end);
}
extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* param2)
@ -805,28 +805,28 @@ extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* par
case DBG_FUNCTION_GET:
{
FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1;
return (uint)functionget(info->addr, &info->start, &info->end);
return (uint)FunctionGet(info->addr, &info->start, &info->end);
}
break;
case DBG_FUNCTION_OVERLAPS:
{
FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1;
return (uint)functionoverlaps(info->start, info->end);
return (uint)FunctionOverlaps(info->start, info->end);
}
break;
case DBG_FUNCTION_ADD:
{
FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1;
return (uint)functionadd(info->start, info->end, info->manual);
return (uint)FunctionAdd(info->start, info->end, info->manual);
}
break;
case DBG_FUNCTION_DEL:
{
FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1;
return (uint)functiondel(info->addr);
return (uint)FunctionDelete(info->addr);
}
break;
@ -899,25 +899,25 @@ extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* par
case DBG_SET_AUTO_BOOKMARK_AT:
{
return (uint)bookmarkset((uint)param1, false);
return (uint)BookmarkSet((uint)param1, false);
}
break;
case DBG_DELETE_AUTO_BOOKMARK_RANGE:
{
bookmarkdelrange((uint)param1, (uint)param2);
BookmarkDelRange((uint)param1, (uint)param2);
}
break;
case DBG_SET_AUTO_FUNCTION_AT:
{
return (uint)functionadd((uint)param1, (uint)param2, false);
return (uint)FunctionAdd((uint)param1, (uint)param2, false);
}
break;
case DBG_DELETE_AUTO_FUNCTION_RANGE:
{
functiondelrange((uint)param1, (uint)param2);
FunctionDelRange((uint)param1, (uint)param2);
}
break;

View File

@ -23,8 +23,8 @@ void dbsave()
JSON root = json_object();
commentcachesave(root);
labelcachesave(root);
bookmarkcachesave(root);
functioncachesave(root);
BookmarkCacheSave(root);
FunctionCacheSave(root);
loopcachesave(root);
BpCacheSave(root);
WString wdbpath = StringUtils::Utf8ToUtf16(dbpath);
@ -84,8 +84,8 @@ void dbload()
}
commentcacheload(root);
labelcacheload(root);
bookmarkcacheload(root);
functioncacheload(root);
BookmarkCacheLoad(root);
FunctionCacheLoad(root);
loopcacheload(root);
BpCacheLoad(root);
json_decref(root); //free root
@ -97,8 +97,8 @@ void dbclose()
dbsave();
commentclear();
labelclear();
bookmarkclear();
functionclear();
BookmarkClear();
FunctionClear();
loopclear();
BpClear();
patchclear();

View File

@ -66,12 +66,13 @@ void BookmarkDelRange(uint Start, uint End)
}
else
{
// Make sure 'start' and 'end' reference the same module
// Make sure 'Start' and 'End' reference the same module
uint moduleBase = ModBaseFromAddr(Start);
if(moduleBase != ModBaseFromAddr(End))
return;
// Virtual -> relative offset
Start -= moduleBase;
End -= moduleBase;

View File

@ -813,8 +813,8 @@ CMDRESULT cbDebugBenchmark(int argc, char* argv[])
{
commentset(i, "test", false);
labelset(i, "test", false);
bookmarkset(i, false);
functionadd(i, i, false);
BookmarkSet(i, false);
FunctionAdd(i, i, false);
}
dprintf("%ums\n", GetTickCount() - ticks);
return STATUS_CONTINUE;

View File

@ -8,185 +8,256 @@ typedef std::map<ModuleRange, FUNCTIONSINFO, ModuleRangeCompare> FunctionsInfo;
static FunctionsInfo functions;
bool functionadd(uint start, uint end, bool manual)
bool FunctionAdd(uint Start, uint End, bool Manual)
{
if(!DbgIsDebugging() or end < start or !memisvalidreadptr(fdProcessInfo->hProcess, start))
// CHECK: Export/Command function
if(!DbgIsDebugging())
return false;
const uint modbase = ModBaseFromAddr(start);
if(modbase != ModBaseFromAddr(end)) //the function boundaries are not in the same module
// Make sure memory is readable
if(!memisvalidreadptr(fdProcessInfo->hProcess, Start))
return false;
if(functionoverlaps(start, end))
// 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 - modbase;
function.end = end - modbase;
function.manual = manual;
CriticalSectionLocker locker(LockFunctions);
functions.insert(std::make_pair(ModuleRange(ModHashFromAddr(modbase), Range(function.start, function.end)), 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 addr, uint* start, uint* end)
bool FunctionGet(uint Address, uint* Start, uint* End)
{
// CHECK: Exported function
if(!DbgIsDebugging())
return false;
uint modbase = ModBaseFromAddr(addr);
CriticalSectionLocker locker(LockFunctions);
const FunctionsInfo::iterator found = functions.find(ModuleRange(ModHashFromAddr(modbase), Range(addr - modbase, addr - modbase)));
if(found == functions.end()) //not found
const uint modbase = ModBaseFromAddr(Address);
// Lookup by module hash, then function range
SHARED_ACQUIRE(LockFunctions);
auto found = functions.find(ModuleRange(ModHashFromAddr(modbase), Range(Address - modbase, Address - modbase)));
// Was this range found?
if(found == functions.end())
return false;
if(start)
*start = found->second.start + modbase;
if(end)
*end = found->second.end + modbase;
if(Start)
*Start = found->second.start + modbase;
if(End)
*End = found->second.end + modbase;
return true;
}
bool functionoverlaps(uint start, uint end)
{
if(!DbgIsDebugging() or end < start)
return false;
const uint modbase = ModBaseFromAddr(start);
CriticalSectionLocker locker(LockFunctions);
return (functions.count(ModuleRange(ModHashFromAddr(modbase), Range(start - modbase, end - modbase))) > 0);
}
bool functiondel(uint addr)
bool FunctionOverlaps(uint Start, uint End)
{
// CHECK: Exported function
if(!DbgIsDebugging())
return false;
const uint modbase = ModBaseFromAddr(addr);
CriticalSectionLocker locker(LockFunctions);
return (functions.erase(ModuleRange(ModHashFromAddr(modbase), Range(addr - modbase, addr - modbase))) > 0);
// 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);
}
void functiondelrange(uint start, uint end)
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);
}
void FunctionDelRange(uint Start, uint End)
{
// CHECK: Exported function
if(!DbgIsDebugging())
return;
bool bDelAll = (start == 0 && end == ~0); //0x00000000-0xFFFFFFFF
uint modbase = ModBaseFromAddr(start);
if(modbase != ModBaseFromAddr(end))
return;
start -= modbase;
end -= modbase;
CriticalSectionLocker locker(LockFunctions);
FunctionsInfo::iterator i = functions.begin();
while(i != functions.end())
// Should all functions be deleted?
if(Start == 0x00000000 && End == 0xFFFFFFFF)
{
if(i->second.manual) //ignore manual
EXCLUSIVE_ACQUIRE(LockFunctions);
functions.clear();
}
else
{
uint moduleBase = ModBaseFromAddr(Start);
// The start and end address must be in the same module
if(moduleBase != ModBaseFromAddr(End))
return;
// Convert these to a relative offset
Start -= moduleBase;
End -= moduleBase;
EXCLUSIVE_ACQUIRE(LockFunctions);
for(auto itr = functions.begin(); itr != functions.end();)
{
i++;
continue;
// Ignore manually set entries
if(itr->second.manual)
{
itr++;
continue;
}
// [Start, End]
if(itr->second.end >= Start && itr->second.start <= End)
itr = functions.erase(itr);
else
itr++;
}
if(bDelAll or !(i->second.start <= end and i->second.end >= start))
functions.erase(i++);
else
i++;
}
}
void functioncachesave(JSON root)
void FunctionCacheSave(JSON Root)
{
CriticalSectionLocker locker(LockFunctions);
const JSON jsonfunctions = json_array();
const JSON jsonautofunctions = json_array();
for(FunctionsInfo::iterator i = functions.begin(); i != functions.end(); ++i)
EXCLUSIVE_ACQUIRE(LockFunctions);
// Allocate JSON object array
const JSON jsonFunctions = json_array();
const JSON jsonAutoFunctions = json_array();
for(auto & i : functions)
{
const FUNCTIONSINFO curFunction = i->second;
JSON curjsonfunction = json_object();
json_object_set_new(curjsonfunction, "module", json_string(curFunction.mod));
json_object_set_new(curjsonfunction, "start", json_hex(curFunction.start));
json_object_set_new(curjsonfunction, "end", json_hex(curFunction.end));
if(curFunction.manual)
json_array_append_new(jsonfunctions, curjsonfunction);
JSON currentFunction = json_object();
json_object_set_new(currentFunction, "module", json_string(i.second.mod));
json_object_set_new(currentFunction, "start", json_hex(i.second.start));
json_object_set_new(currentFunction, "end", json_hex(i.second.end));
if(i.second.manual)
json_array_append_new(jsonFunctions, currentFunction);
else
json_array_append_new(jsonautofunctions, curjsonfunction);
json_array_append_new(jsonAutoFunctions, currentFunction);
}
if(json_array_size(jsonfunctions))
json_object_set(root, "functions", jsonfunctions);
json_decref(jsonfunctions);
if(json_array_size(jsonautofunctions))
json_object_set(root, "autofunctions", jsonautofunctions);
json_decref(jsonautofunctions);
if(json_array_size(jsonFunctions))
json_object_set(Root, "functions", jsonFunctions);
if(json_array_size(jsonAutoFunctions))
json_object_set(Root, "autofunctions", jsonAutoFunctions);
// Decrease reference count to avoid leaking memory
json_decref(jsonFunctions);
json_decref(jsonAutoFunctions);
}
void functioncacheload(JSON root)
void FunctionCacheLoad(JSON Root)
{
CriticalSectionLocker locker(LockFunctions);
EXCLUSIVE_ACQUIRE(LockFunctions);
// Delete existing entries
functions.clear();
const JSON jsonfunctions = json_object_get(root, "functions");
if(jsonfunctions)
// Inline lambda to enumerate all JSON array indices
auto InsertFunctions = [](const JSON Object, bool Manual)
{
size_t i;
JSON value;
json_array_foreach(jsonfunctions, i, value)
json_array_foreach(Object, i, value)
{
FUNCTIONSINFO curFunction;
FUNCTIONSINFO function;
// Copy module name
const char* mod = json_string_value(json_object_get(value, "module"));
if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE)
strcpy_s(curFunction.mod, mod);
strcpy_s(function.mod, mod);
else
*curFunction.mod = '\0';
curFunction.start = (uint)json_hex_value(json_object_get(value, "start"));
curFunction.end = (uint)json_hex_value(json_object_get(value, "end"));
if(curFunction.end < curFunction.start)
continue; //invalid function
curFunction.manual = true;
const uint key = ModHashFromName(curFunction.mod);
functions.insert(std::make_pair(ModuleRange(ModHashFromName(curFunction.mod), Range(curFunction.start, curFunction.end)), curFunction));
function.mod[0] = '\0';
// Function address
function.start = (uint)json_hex_value(json_object_get(value, "start"));
function.end = (uint)json_hex_value(json_object_get(value, "end"));
function.manual = Manual;
// Sanity check
if(function.end < function.start)
continue;
const uint key = ModHashFromName(function.mod);
functions.insert(std::make_pair(ModuleRange(ModHashFromName(function.mod), Range(function.start, function.end)), function));
}
}
JSON jsonautofunctions = json_object_get(root, "autofunctions");
if(jsonautofunctions)
{
size_t i;
JSON value;
json_array_foreach(jsonautofunctions, i, value)
{
FUNCTIONSINFO curFunction;
const char* mod = json_string_value(json_object_get(value, "module"));
if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE)
strcpy_s(curFunction.mod, mod);
else
*curFunction.mod = '\0';
curFunction.start = (uint)json_hex_value(json_object_get(value, "start"));
curFunction.end = (uint)json_hex_value(json_object_get(value, "end"));
if(curFunction.end < curFunction.start)
continue; //invalid function
curFunction.manual = true;
const uint key = ModHashFromName(curFunction.mod);
functions.insert(std::make_pair(ModuleRange(ModHashFromName(curFunction.mod), Range(curFunction.start, curFunction.end)), curFunction));
}
}
};
const JSON jsonFunctions = json_object_get(Root, "functions");
const JSON jsonAutoFunctions = json_object_get(Root, "autofunctions");
if(jsonFunctions)
InsertFunctions(jsonFunctions, true);
if(jsonAutoFunctions)
InsertFunctions(jsonAutoFunctions, false);
}
bool functionenum(FUNCTIONSINFO* functionlist, size_t* cbsize)
bool FunctionEnum(FUNCTIONSINFO* List, size_t* Size)
{
// CHECK: Exported function
if(!DbgIsDebugging())
return false;
if(!functionlist && !cbsize)
// If a list isn't passed and the size not requested, fail
if(!List && !Size)
return false;
CriticalSectionLocker locker(LockFunctions);
if(!functionlist && cbsize)
SHARED_ACQUIRE(LockFunctions);
// Did the caller request the buffer size needed?
if(Size)
{
*cbsize = functions.size() * sizeof(FUNCTIONSINFO);
return true;
*Size = functions.size() * sizeof(FUNCTIONSINFO);
if(!List)
return true;
}
int j = 0;
for(FunctionsInfo::iterator i = functions.begin(); i != functions.end(); ++i, j++)
// Fill out the buffer
for(auto & itr : functions)
{
functionlist[j] = i->second;
uint modbase = ModBaseFromName(functionlist[j].mod);
functionlist[j].start += modbase;
functionlist[j].end += modbase;
// Adjust for relative to virtual addresses
uint moduleBase = ModBaseFromName(itr.second.mod);
*List = itr.second;
List->start += moduleBase;
List->end += moduleBase;
List++;
}
return true;
}
void functionclear()
void FunctionClear()
{
CriticalSectionLocker locker(LockFunctions);
FunctionsInfo().swap(functions);
EXCLUSIVE_ACQUIRE(LockFunctions);
functions.clear();
}

View File

@ -1,5 +1,4 @@
#ifndef _FUNCTION_H
#define _FUNCTION_H
#pragma once
#include "addrinfo.h"
@ -11,14 +10,12 @@ struct FUNCTIONSINFO
bool manual;
};
bool functionadd(uint start, uint end, bool manual);
bool functionget(uint addr, uint* start, uint* end);
bool functionoverlaps(uint start, uint end);
bool functiondel(uint addr);
void functiondelrange(uint start, uint end);
void functioncachesave(JSON root);
void functioncacheload(JSON root);
bool functionenum(FUNCTIONSINFO* functionlist, size_t* cbsize);
void functionclear();
#endif //_FUNCTION_H
bool FunctionAdd(uint Start, uint End, bool Manual);
bool FunctionGet(uint Address, uint* Start, uint* End);
bool FunctionOverlaps(uint Start, uint End);
bool FunctionDelete(uint Address);
void FunctionDelRange(uint Start, uint End);
void FunctionCacheSave(JSON Root);
void FunctionCacheLoad(JSON Root);
bool FunctionEnum(FUNCTIONSINFO* List, size_t* Size);
void FunctionClear();

View File

@ -368,7 +368,7 @@ CMDRESULT cbInstrBookmarkSet(int argc, char* argv[])
uint addr = 0;
if(!valfromstring(argv[1], &addr, false))
return STATUS_ERROR;
if(!bookmarkset(addr, true))
if(!BookmarkSet(addr, true))
{
dputs("failed to set bookmark!");
return STATUS_ERROR;
@ -387,7 +387,7 @@ CMDRESULT cbInstrBookmarkDel(int argc, char* argv[])
uint addr = 0;
if(!valfromstring(argv[1], &addr, false))
return STATUS_ERROR;
if(!bookmarkdel(addr))
if(!BookmarkDelete(addr))
{
dputs("failed to delete bookmark!");
return STATUS_ERROR;
@ -454,7 +454,7 @@ CMDRESULT cbFunctionAdd(int argc, char* argv[])
uint end = 0;
if(!valfromstring(argv[1], &start, false) or !valfromstring(argv[2], &end, false))
return STATUS_ERROR;
if(!functionadd(start, end, true))
if(!FunctionAdd(start, end, true))
{
dputs("failed to add function");
return STATUS_ERROR;
@ -474,7 +474,7 @@ CMDRESULT cbFunctionDel(int argc, char* argv[])
uint addr = 0;
if(!valfromstring(argv[1], &addr, false))
return STATUS_ERROR;
if(!functiondel(addr))
if(!FunctionDelete(addr))
{
dputs("failed to delete function");
return STATUS_ERROR;
@ -1339,14 +1339,14 @@ CMDRESULT cbInstrBookmarkList(int argc, char* argv[])
GuiReferenceAddColumn(0, "Disassembly");
GuiReferenceReloadData();
size_t cbsize;
bookmarkenum(0, &cbsize);
BookmarkEnum(0, &cbsize);
if(!cbsize)
{
dputs("no bookmarks");
return STATUS_CONTINUE;
}
Memory<BOOKMARKSINFO*> bookmarks(cbsize, "cbInstrBookmarkList:bookmarks");
bookmarkenum(bookmarks, 0);
BookmarkEnum(bookmarks, 0);
int count = (int)(cbsize / sizeof(BOOKMARKSINFO));
for(int i = 0; i < count; i++)
{
@ -1374,14 +1374,14 @@ CMDRESULT cbInstrFunctionList(int argc, char* argv[])
GuiReferenceAddColumn(0, "Label/Comment");
GuiReferenceReloadData();
size_t cbsize;
functionenum(0, &cbsize);
FunctionEnum(0, &cbsize);
if(!cbsize)
{
dputs("no functions");
return STATUS_CONTINUE;
}
Memory<FUNCTIONSINFO*> functions(cbsize, "cbInstrFunctionList:functions");
functionenum(functions, 0);
FunctionEnum(functions, 0);
int count = (int)(cbsize / sizeof(FUNCTIONSINFO));
for(int i = 0; i < count; i++)
{

View File

@ -105,7 +105,6 @@ bool ModUnload(uint base)
void ModClear()
{
// Remove all modules in the list
EXCLUSIVE_ACQUIRE(LockModules);
modinfo.clear();
EXCLUSIVE_RELEASE();
@ -141,13 +140,9 @@ bool ModNameFromAddr(uint addr, char* modname, bool extension)
if(!module)
return false;
// Zero buffer first
memset(modname, 0, MAX_MODULE_SIZE);
// Copy initial module name
strcpy_s(modname, MAX_MODULE_SIZE, module->name);
// Append the module path/name
strcat_s(modname, MAX_MODULE_SIZE, module->name);
// Append the extension
if(extension)
strcat_s(modname, MAX_MODULE_SIZE, module->extension);