1
0
Fork 0
x64dbg/x64_dbg_dbg/addrinfo.cpp

737 lines
26 KiB
C++

#include "addrinfo.h"
#include "debugger.h"
#include "console.h"
#include "memory.h"
#include "sqlhelper.h"
#include "breakpoint.h"
#include "threading.h"
#include "symbolinfo.h"
sqlite3* userdb;
static std::vector<MODINFO> modinfo;
///basic database functions
void dbinit()
{
//initialize user database
lock(WAITID_USERDB);
if(sqlite3_open(":memory:", &userdb))
{
unlock(WAITID_USERDB);
dputs("failed to open database!");
return;
}
unlock(WAITID_USERDB);
sqlloadsavedb(userdb, dbpath, false);
if(!sqlexec(userdb, "CREATE TABLE IF NOT EXISTS labels (id INTEGER PRIMARY KEY AUTOINCREMENT, mod TEXT, addr INT64 NOT NULL, text TEXT NOT NULL)"))
dprintf("SQL Error: %s\n", sqllasterror());
if(!sqlexec(userdb, "CREATE TABLE IF NOT EXISTS comments (id INTEGER PRIMARY KEY AUTOINCREMENT, mod TEXT, addr INT64 NOT NULL, text TEXT NOT NULL)"))
dprintf("SQL Error: %s\n", sqllasterror());
if(!sqlexec(userdb, "CREATE TABLE IF NOT EXISTS bookmarks (id INTEGER PRIMARY KEY AUTOINCREMENT, mod TEXT, addr INT64 NOT NULL)"))
dprintf("SQL Error: %s\n", sqllasterror());
if(!sqlexec(userdb, "CREATE TABLE IF NOT EXISTS breakpoints (id INTEGER PRIMARY KEY AUTOINCREMENT, addr INT64 NOT NULL, enabled INT NOT NULL, singleshoot INT NOT NULL, oldbytes INT NOT NULL, type INT NOT NULL, titantype INT NOT NULL, mod TEXT, name TEXT)"))
dprintf("SQL Error: %s\n", sqllasterror());
if(!sqlexec(userdb, "CREATE TABLE IF NOT EXISTS functions (id INTEGER PRIMARY KEY AUTOINCREMENT, mod TEXT, start INT64 NOT NULL, end INT64 NOT NULL, manual BOOL NOT NULL)"))
dprintf("SQL Error: %s\n", sqllasterror());
if(!sqlexec(userdb, "CREATE TABLE IF NOT EXISTS loops (id INTEGER PRIMARY KEY AUTOINCREMENT, mod TEXT, start INT64 NOT NULL, end INT64 NOT NULL, parent INT, depth INT NOT NULL, manual BOOL NOT NULL)"))
dprintf("SQL Error: %s\n", sqllasterror());
dbsave();
bpenumall(0); //update breakpoint list
GuiUpdateBreakpointsView();
}
bool dbload()
{
if(!FileExists(dbpath))
{
dbinit();
return true;
}
return sqlloadsavedb(userdb, dbpath, false);
}
bool dbsave()
{
CreateDirectoryA(sqlitedb_basedir, 0); //create database directory
return sqlloadsavedb(userdb, dbpath, true);
}
void dbclose()
{
//NOTE: remove breakpoints without module
if(!sqlexec(userdb, "DELETE FROM breakpoints WHERE mod IS NULL"))
dprintf("SQL Error: %s\n", sqllasterror());
//NOTE: remove singleshoot breakpoints (mostly temporary breakpoints)
if(!sqlexec(userdb, "DELETE FROM breakpoints WHERE singleshoot=1 AND type=0"))
dprintf("SQL Error: %s\n", sqllasterror());
dbsave();
wait(WAITID_USERDB); //wait for the SQLite operation to complete before closing
lock(WAITID_USERDB);
sqlite3_db_release_memory(userdb);
sqlite3_close(userdb); //close user database
unlock(WAITID_USERDB);
}
///module functions
bool modload(uint base, uint size, const char* fullpath)
{
if(!base or !size or !fullpath)
return false;
char name[deflen]="";
int len=strlen(fullpath);
while(fullpath[len]!='\\' and len)
len--;
if(len)
len++;
strcpy(name, fullpath+len);
len=strlen(name);
name[MAX_MODULE_SIZE-1]=0; //ignore later characters
while(name[len]!='.' and len)
len--;
MODINFO info;
memset(&info, 0, sizeof(MODINFO));
if(len)
{
strcpy(info.extension, name+len);
_strlwr(info.extension);
name[len]=0; //remove extension
}
info.base=base;
info.size=size;
strcpy(info.name, name);
_strlwr(info.name);
modinfo.push_back(info);
symupdatemodulelist();
return true;
}
bool modunload(uint base)
{
int total=modinfo.size();
for(int i=0; i<total; i++)
{
if(modinfo.at(i).base==base)
{
modinfo.erase(modinfo.begin()+i);
symupdatemodulelist();
return true;
}
}
return false;
}
void modclear()
{
std::vector<MODINFO>().swap(modinfo);
symupdatemodulelist();
}
bool modnamefromaddr(uint addr, char* modname, bool extension)
{
if(!modname)
return false;
int total=modinfo.size();
for(int i=0; i<total; i++)
{
uint modstart=modinfo.at(i).base;
uint modend=modstart+modinfo.at(i).size;
if(addr>=modstart and addr<modend) //found module
{
strcpy(modname, modinfo.at(i).name);
if(extension)
strcat(modname, modinfo.at(i).extension); //append extension
return true;
}
}
return false;
}
uint modbasefromaddr(uint addr)
{
int total=modinfo.size();
for(int i=0; i<total; i++)
{
uint modstart=modinfo.at(i).base;
uint modend=modstart+modinfo.at(i).size;
if(addr>=modstart and addr<modend) //found module
return modstart;
}
return 0;
}
uint modbasefromname(const char* modname)
{
if(!modname)
return 0;
int total=modinfo.size();
int modname_len=strlen(modname);
if(modname_len>=MAX_MODULE_SIZE)
return 0;
for(int i=0; i<total; i++)
{
char curmodname[MAX_MODULE_SIZE]="";
sprintf(curmodname, "%s%s", modinfo.at(i).name, modinfo.at(i).extension);
if(!_stricmp(curmodname, modname)) //with extension
return modinfo.at(i).base;
if(!_stricmp(modinfo.at(i).name, modname)) //without extension
return modinfo.at(i).base;
}
return 0;
}
///api functions
bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum)
{
MEMORY_BASIC_INFORMATION mbi;
VirtualQueryEx(fdProcessInfo->hProcess, (const void*)base, &mbi, sizeof(mbi));
uint size=mbi.RegionSize;
void* buffer=emalloc(size, "apienumexports:buffer");
if(!memread(fdProcessInfo->hProcess, (const void*)base, buffer, size, 0))
{
efree(buffer, "apienumexports:buffer");
return false;
}
IMAGE_NT_HEADERS* pnth=(IMAGE_NT_HEADERS*)((uint)buffer+GetPE32DataFromMappedFile((ULONG_PTR)buffer, 0, UE_PE_OFFSET));
uint export_dir_rva=pnth->OptionalHeader.DataDirectory[0].VirtualAddress;
uint export_dir_size=pnth->OptionalHeader.DataDirectory[0].Size;
efree(buffer, "apienumexports:buffer");
IMAGE_EXPORT_DIRECTORY export_dir;
memset(&export_dir, 0, sizeof(export_dir));
memread(fdProcessInfo->hProcess, (const void*)(export_dir_rva+base), &export_dir, sizeof(export_dir), 0);
unsigned int NumberOfNames=export_dir.NumberOfNames;
if(!export_dir.NumberOfFunctions or !NumberOfNames) //no named exports
return false;
char modname[MAX_MODULE_SIZE]="";
modnamefromaddr(base, modname, true);
uint original_name_va=export_dir.Name+base;
char original_name[deflen]="";
memset(original_name, 0, sizeof(original_name));
memread(fdProcessInfo->hProcess, (const void*)original_name_va, original_name, deflen, 0);
char* AddrOfFunctions_va=(char*)(export_dir.AddressOfFunctions+base);
char* AddrOfNames_va=(char*)(export_dir.AddressOfNames+base);
char* AddrOfNameOrdinals_va=(char*)(export_dir.AddressOfNameOrdinals+base);
for(DWORD i=0; i<NumberOfNames; i++)
{
DWORD curAddrOfName=0;
memread(fdProcessInfo->hProcess, AddrOfNames_va+sizeof(DWORD)*i, &curAddrOfName, sizeof(DWORD), 0);
char* cur_name_va=(char*)(curAddrOfName+base);
char cur_name[deflen]="";
memset(cur_name, 0, deflen);
memread(fdProcessInfo->hProcess, cur_name_va, cur_name, deflen, 0);
WORD curAddrOfNameOrdinals=0;
memread(fdProcessInfo->hProcess, AddrOfNameOrdinals_va+sizeof(WORD)*i, &curAddrOfNameOrdinals, sizeof(WORD), 0);
DWORD curFunctionRva=0;
memread(fdProcessInfo->hProcess, AddrOfFunctions_va+sizeof(DWORD)*curAddrOfNameOrdinals, &curFunctionRva, sizeof(DWORD), 0);
if(curFunctionRva>=export_dir_rva and curFunctionRva<export_dir_rva+export_dir_size)
{
char forwarded_api[deflen]="";
memset(forwarded_api, 0, deflen);
memread(fdProcessInfo->hProcess, (void*)(curFunctionRva+base), forwarded_api, deflen, 0);
int len=strlen(forwarded_api);
int j=0;
while(forwarded_api[j]!='.' and j<len)
j++;
if(forwarded_api[j]=='.')
{
forwarded_api[j]=0;
HINSTANCE hTempDll=LoadLibraryExA(forwarded_api, 0, DONT_RESOLVE_DLL_REFERENCES|LOAD_LIBRARY_AS_DATAFILE);
if(hTempDll)
{
uint local_addr=(uint)GetProcAddress(hTempDll, forwarded_api+j+1);
if(local_addr)
{
uint remote_addr=ImporterGetRemoteAPIAddress(fdProcessInfo->hProcess, local_addr);
cbEnum(base, modname, cur_name, remote_addr);
}
}
}
}
else
{
cbEnum(base, modname, cur_name, curFunctionRva+base);
}
}
return true;
}
///comment functions
bool commentset(uint addr, const char* text)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr) or !text or strlen(text)>=MAX_COMMENT_SIZE-1)
return false;
if(!*text) //NOTE: delete when there is no text
return commentdel(addr);
char commenttext[MAX_COMMENT_SIZE]="";
sqlstringescape(text, commenttext);
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
if(!modnamefromaddr(addr, modname, true)) //comments without module
{
sprintf(sql, "SELECT text FROM comments WHERE mod IS NULL AND addr=%"fext"d", addr);
if(sqlhasresult(userdb, sql)) //there is a comment already
sprintf(sql, "UPDATE comments SET text='%s' WHERE mod IS NULL AND addr=%"fext"d", commenttext, addr);
else //insert
sprintf(sql, "INSERT INTO comments (addr,text) VALUES (%"fext"d,'%s')", addr, commenttext);
}
else
{
uint modbase=modbasefromaddr(addr);
uint rva=addr-modbase;
sprintf(sql, "SELECT text FROM comments WHERE mod='%s' AND addr=%"fext"d", modname, rva);
if(sqlhasresult(userdb, sql)) //there is a comment already
sprintf(sql, "UPDATE comments SET text='%s' WHERE mod='%s' AND addr=%"fext"d", commenttext, modname, rva);
else //insert
sprintf(sql, "INSERT INTO comments (mod,addr,text) VALUES ('%s',%"fext"d,'%s')", modname, rva, commenttext);
}
if(!sqlexec(userdb, sql))
{
dprintf("SQL Error: %s\nSQL Query: %s\n", sqllasterror(), sql);
return false;
}
GuiUpdateAllViews();
dbsave();
return true;
}
bool commentget(uint addr, char* text)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr) or !text)
return false;
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
if(!modnamefromaddr(addr, modname, true)) //comments without module
sprintf(sql, "SELECT text FROM comments WHERE mod IS NULL AND addr=%"fext"d", addr);
else
sprintf(sql, "SELECT text FROM comments WHERE mod='%s' AND addr=%"fext"d", modname, addr-modbasefromaddr(addr));
return sqlgettext(userdb, sql, text);
}
bool commentdel(uint addr)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr))
return false;
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
if(!modnamefromaddr(addr, modname, true)) //comments without module
sprintf(sql, "SELECT id FROM comments WHERE mod IS NULL AND addr=%"fext"d", addr);
else
{
uint modbase=modbasefromaddr(addr);
uint rva=addr-modbase;
sprintf(sql, "SELECT id FROM comments WHERE mod='%s' AND addr=%"fext"d", modname, rva);
}
int del_id=0;
if(!sqlgetint(userdb, sql, &del_id))
return false;
sprintf(sql, "DELETE FROM comments WHERE id=%d", del_id);
if(!sqlexec(userdb, sql))
{
dprintf("SQL Error: %s\nSQL Query: %s\n", sqllasterror(), sql);
return false;
}
GuiUpdateAllViews();
dbsave();
return true;
}
///label functions
bool labelset(uint addr, const char* text)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr) or !text or strlen(text)>=MAX_LABEL_SIZE-1)
return false;
if(!*text) //NOTE: delete when there is no text
return labeldel(addr);
char labeltext[MAX_LABEL_SIZE]="";
sqlstringescape(text, labeltext);
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
if(!modnamefromaddr(addr, modname, true)) //labels without module
{
sprintf(sql, "SELECT text FROM labels WHERE mod IS NULL AND addr=%"fext"d", addr);
if(sqlhasresult(userdb, sql)) //there is a label already
sprintf(sql, "UPDATE labels SET text='%s' WHERE mod IS NULL AND addr=%"fext"d", labeltext, addr);
else //insert
sprintf(sql, "INSERT INTO labels (addr,text) VALUES (%"fext"d,'%s')", addr, labeltext);
}
else
{
uint modbase=modbasefromaddr(addr);
uint rva=addr-modbase;
sprintf(sql, "SELECT text FROM labels WHERE mod='%s' AND addr=%"fext"d", modname, rva);
if(sqlhasresult(userdb, sql)) //there is a label already
sprintf(sql, "UPDATE labels SET text='%s' WHERE mod='%s' AND addr=%"fext"d", labeltext, modname, rva);
else //insert
sprintf(sql, "INSERT INTO labels (mod,addr,text) VALUES ('%s',%"fext"d,'%s')", modname, rva, labeltext);
}
if(!sqlexec(userdb, sql))
{
dprintf("SQL Error: %s\nSQL Query: %s\n", sqllasterror(), sql);
return false;
}
GuiUpdateAllViews();
dbsave();
return true;
}
bool labelfromstring(const char* text, uint* addr)
{
if(!text or !strlen(text) or !addr)
return 0;
char labeltext[MAX_LABEL_SIZE]="";
sqlstringescape(text, labeltext);
char sql[deflen]="";
sprintf(sql, "SELECT addr,mod FROM labels WHERE text='%s'", labeltext);
sqlite3_stmt* stmt;
lock(WAITID_USERDB);
if(sqlite3_prepare_v2(userdb, sql, -1, &stmt, 0)!=SQLITE_OK)
{
sqlite3_finalize(stmt);
unlock(WAITID_USERDB);
return false;
}
if(sqlite3_step(stmt)!=SQLITE_ROW)
{
sqlite3_finalize(stmt);
unlock(WAITID_USERDB);
return false;
}
#ifdef _WIN64
*addr=sqlite3_column_int64(stmt, 0); //addr
#else
*addr=sqlite3_column_int(stmt, 0); //addr
#endif // _WIN64
const char* modname=(const char*)sqlite3_column_text(stmt, 1); //mod
if(!modname)
{
sqlite3_finalize(stmt);
unlock(WAITID_USERDB);
return true;
}
//TODO: fix this
*addr+=modbasefromname(modname);
sqlite3_finalize(stmt);
unlock(WAITID_USERDB);
return true;
}
bool labelget(uint addr, char* text)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr) or !text)
return false;
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
if(!modnamefromaddr(addr, modname, true)) //labels without module
sprintf(sql, "SELECT text FROM labels WHERE mod IS NULL AND addr=%"fext"d", addr);
else
sprintf(sql, "SELECT text FROM labels WHERE mod='%s' AND addr=%"fext"d", modname, addr-modbasefromaddr(addr));
return sqlgettext(userdb, sql, text);
}
bool labeldel(uint addr)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr))
return false;
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
if(!modnamefromaddr(addr, modname, true)) //labels without module
sprintf(sql, "SELECT id FROM labels WHERE mod IS NULL AND addr=%"fext"d", addr);
else
{
uint modbase=modbasefromaddr(addr);
uint rva=addr-modbase;
sprintf(sql, "SELECT id FROM labels WHERE mod='%s' AND addr=%"fext"d", modname, rva);
}
int del_id=0;
if(!sqlgetint(userdb, sql, &del_id))
return false;
sprintf(sql, "DELETE FROM labels WHERE id=%d", del_id);
if(!sqlexec(userdb, sql))
{
dprintf("SQL Error: %s\nSQL Query: %s\n", sqllasterror(), sql);
return false;
}
dbsave();
GuiUpdateAllViews();
return true;
}
///bookmark functions
bool bookmarkset(uint addr)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr))
return false;
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
if(!modnamefromaddr(addr, modname, true)) //bookmarks without module
{
sprintf(sql, "SELECT * FROM bookmarks WHERE mod IS NULL AND addr=%"fext"d", addr);
if(sqlhasresult(userdb, sql)) //there is a bookmark already
return true;
else //insert
sprintf(sql, "INSERT INTO bookmarks (addr) VALUES (%"fext"d)", addr);
}
else
{
uint modbase=modbasefromaddr(addr);
uint rva=addr-modbase;
sprintf(sql, "SELECT * FROM bookmarks WHERE mod='%s' AND addr=%"fext"d", modname, rva);
if(sqlhasresult(userdb, sql)) //there is a bookmark already
return true;
else //insert
sprintf(sql, "INSERT INTO bookmarks (mod,addr) VALUES ('%s',%"fext"d)", modname, rva);
}
if(!sqlexec(userdb, sql))
{
dprintf("SQL Error: %s\nSQL Query: %s\n", sqllasterror(), sql);
return false;
}
GuiUpdateAllViews();
dbsave();
return true;
}
bool bookmarkget(uint addr)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr))
return false;
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
if(!modnamefromaddr(addr, modname, true)) //bookmarks without module
sprintf(sql, "SELECT * FROM bookmarks WHERE mod IS NULL AND addr=%"fext"d", addr);
else
sprintf(sql, "SELECT * FROM bookmarks WHERE mod='%s' AND addr=%"fext"d", modname, addr-modbasefromaddr(addr));
return sqlhasresult(userdb, sql);
}
bool bookmarkdel(uint addr)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr))
return false;
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
if(!modnamefromaddr(addr, modname, true)) //bookmarks without module
sprintf(sql, "SELECT id FROM bookmarks WHERE mod IS NULL AND addr=%"fext"d", addr);
else
{
uint modbase=modbasefromaddr(addr);
uint rva=addr-modbase;
sprintf(sql, "SELECT id FROM bookmarks WHERE mod='%s' AND addr=%"fext"d", modname, rva);
}
int del_id=0;
if(!sqlgetint(userdb, sql, &del_id))
return false;
sprintf(sql, "DELETE FROM bookmarks WHERE id=%d", del_id);
if(!sqlexec(userdb, sql))
{
dprintf("SQL Error: %s\nSQL Query: %s\n", sqllasterror(), sql);
return false;
}
dbsave();
GuiUpdateAllViews();
return true;
}
///function database
bool functionget(duint addr, duint* start, duint* end)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr))
return false;
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
uint modbase=0;
if(!modnamefromaddr(addr, modname, true))
sprintf(sql, "SELECT start,end FROM functions WHERE mod IS NULL AND start<=%"fext"d AND end>=%"fext"d", addr, addr);
else
{
modbase=modbasefromaddr(addr);
uint rva=addr-modbase;
sprintf(sql, "SELECT start,end FROM functions WHERE mod='%s' AND start<=%"fext"d AND end>=%"fext"d", modname, rva, rva);
}
sqlite3_stmt* stmt;
lock(WAITID_USERDB);
if(sqlite3_prepare_v2(userdb, sql, -1, &stmt, 0)!=SQLITE_OK)
{
sqlite3_finalize(stmt);
unlock(WAITID_USERDB);
return false;
}
if(sqlite3_step(stmt)!=SQLITE_ROW)
{
sqlite3_finalize(stmt);
unlock(WAITID_USERDB);
return false;
}
#ifdef _WIN64
uint dbstart=sqlite3_column_int64(stmt, 0)+modbase; //start
uint dbend=sqlite3_column_int64(stmt, 1)+modbase; //end
#else
uint dbstart=sqlite3_column_int(stmt, 0)+modbase; //addr
uint dbend=sqlite3_column_int(stmt, 1)+modbase; //end
#endif // _WIN64
sqlite3_finalize(stmt);
if(start)
*start=dbstart;
if(end)
*end=dbend;
unlock(WAITID_USERDB);
return true;
}
bool functionoverlaps(uint start, uint end)
{
char sql[deflen]="";
char modname[MAX_MODULE_SIZE]="";
//check for function overlaps
if(!modnamefromaddr(start, modname, true))
sprintf(sql, "SELECT manual FROM functions WHERE mod IS NULL AND start<=%"fext"d AND end>=%"fext"d", end, start);
else
{
uint modbase=modbasefromaddr(start);
sprintf(sql, "SELECT manual FROM functions WHERE mod='%s' AND start<=%"fext"d AND end>=%"fext"d", modname, end-modbase, start-modbase);
}
if(sqlhasresult(userdb, sql)) //functions overlap
return true;
return false;
}
bool functionadd(uint start, uint end, bool manual)
{
if(!DbgIsDebugging() or end<start or memfindbaseaddr(fdProcessInfo->hProcess, start, 0)!=memfindbaseaddr(fdProcessInfo->hProcess, end, 0)) //the function boundaries are not in the same mem page
return false;
char sql[deflen]="";
char modname[MAX_MODULE_SIZE]="";
uint modbase=0;
//check for function overlaps
if(!modnamefromaddr(start, modname, true))
sprintf(sql, "SELECT manual FROM functions WHERE mod IS NULL AND start<=%"fext"d AND end>=%"fext"d", end, start);
else
{
modbase=modbasefromaddr(start);
sprintf(sql, "SELECT manual FROM functions WHERE mod='%s' AND start<=%"fext"d AND end>=%"fext"d", modname, end-modbase, start-modbase);
}
if(sqlhasresult(userdb, sql)) //functions overlap
return false;
if(modbase)
sprintf(sql, "INSERT INTO functions (mod,start,end,manual) VALUES('%s',%"fext"d,%"fext"d,%d)", modname, start-modbase, end-modbase, manual);
else
sprintf(sql, "INSERT INTO functions (start,end,manual) VALUES(%"fext"d,%"fext"d,%d)", start, end, manual);
if(!sqlexec(userdb, sql))
{
dprintf("SQL Error: %s\nSQL Query: %s\n", sqllasterror(), sql);
return false;
}
GuiUpdateAllViews();
dbsave();
return true;
}
bool functiondel(uint addr)
{
if(!DbgIsDebugging() or !functionget(addr, 0, 0))
return false;
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
if(!modnamefromaddr(addr, modname, true))
sprintf(sql, "DELETE FROM functions WHERE mod IS NULL AND start<=%"fext"d AND end>=%"fext"d", addr, addr);
else
{
uint rva=addr-modbasefromaddr(addr);
sprintf(sql, "DELETE FROM functions WHERE mod='%s' AND start<=%"fext"d AND end>=%"fext"d", modname, rva, rva);
}
if(!sqlexec(userdb, sql))
{
dprintf("SQL Error: %s\nSQL Query: %s\n", sqllasterror(), sql);
return false;
}
GuiUpdateAllViews();
dbsave();
return true;
}
bool loopget(int depth, uint addr, uint* start, uint* end)
{
if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr))
return false;
char modname[MAX_MODULE_SIZE]="";
char sql[deflen]="";
uint modbase=0;
if(!modnamefromaddr(addr, modname, true))
sprintf(sql, "SELECT start,end FROM loops WHERE mod IS NULL AND start<=%"fext"d AND end>=%"fext"d AND depth=%d", addr, addr, depth);
else
{
modbase=modbasefromaddr(addr);
uint rva=addr-modbase;
sprintf(sql, "SELECT start,end FROM loops WHERE mod='%s' AND start<=%"fext"d AND end>=%"fext"d AND depth=%d", modname, rva, rva, depth);
}
sqlite3_stmt* stmt;
lock(WAITID_USERDB);
if(sqlite3_prepare_v2(userdb, sql, -1, &stmt, 0)!=SQLITE_OK)
{
sqlite3_finalize(stmt);
unlock(WAITID_USERDB);
return false;
}
if(sqlite3_step(stmt)!=SQLITE_ROW)
{
sqlite3_finalize(stmt);
unlock(WAITID_USERDB);
return false;
}
#ifdef _WIN64
uint dbstart=sqlite3_column_int64(stmt, 0)+modbase; //start
uint dbend=sqlite3_column_int64(stmt, 1)+modbase; //end
#else
uint dbstart=sqlite3_column_int(stmt, 0)+modbase; //addr
uint dbend=sqlite3_column_int(stmt, 1)+modbase; //end
#endif // _WIN64
sqlite3_finalize(stmt);
if(start)
*start=dbstart;
if(end)
*end=dbend;
unlock(WAITID_USERDB);
return true;
}
bool loopadd(uint start, uint end, bool manual)
{
return false;
}
//check if a loop overlaps a range, inside is not overlapping
bool loopoverlaps(int depth, uint start, uint end)
{
char sql[deflen]="";
char modname[MAX_MODULE_SIZE]="";
//check if the new loop fits in the old loop
if(!modnamefromaddr(start, modname, true))
sprintf(sql, "SELECT manual FROM loops WHERE mod IS NULL AND start<%"fext"d AND end>%"fext"d AND depth=%d", start, end, depth);
else
{
uint modbase=modbasefromaddr(start);
sprintf(sql, "SELECT manual FROM loops WHERE mod='%s' AND start<%"fext"d AND end>%"fext"d AND depth=%d", modname, start-modbase, end-modbase, depth);
}
if(sqlhasresult(userdb, sql)) //new loop fits in the old loop
return loopoverlaps(depth+1, start, end); //check the next depth
//check for loop overlaps
if(!modnamefromaddr(start, modname, true))
sprintf(sql, "SELECT manual FROM loops WHERE mod IS NULL AND start<=%"fext"d AND end>=%"fext"d AND depth=%d", end, start, depth);
else
{
uint modbase=modbasefromaddr(start);
sprintf(sql, "SELECT manual FROM loops WHERE mod='%s' AND start<=%"fext"d AND end>=%"fext"d AND depth=%d", modname, end-modbase, start-modbase, depth);
}
if(sqlhasresult(userdb, sql)) //loops overlap
return true;
return false;
}
bool loopdel(int depth, uint addr)
{
return false;
}