DBG: started with the new breakpoint system (currently only SetBPX and DeleteBPX work, hardware, memory dont work)
This commit is contained in:
parent
2ea70c2d7e
commit
7b338c4199
|
@ -180,17 +180,16 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoset(duint addr, ADDRINFO* addrinfo)
|
|||
|
||||
extern "C" DLL_EXPORT int _dbg_bpgettypeat(duint addr)
|
||||
{
|
||||
int result=bpnone;
|
||||
BREAKPOINT* found=bpfind(bplist, 0, addr, 0, BPNORMAL);
|
||||
if(found and found->enabled) //none found or disabled
|
||||
BREAKPOINT bp;
|
||||
int result=0;
|
||||
if(bpget(addr, BPNORMAL, &bp))
|
||||
result|=bpnormal;
|
||||
found=bpfind(bplist, 0, addr, 0, BPHARDWARE);
|
||||
if(found and found->enabled) //none found or disabled
|
||||
if(bpget(addr, BPHARDWARE, &bp))
|
||||
result|=bphardware;
|
||||
found=bpfind(bplist, 0, addr, 0, BPMEMORY);
|
||||
if(found and found->enabled) //none found or disabled
|
||||
if(bpget(addr, BPMEMORY, &bp))
|
||||
result|=bpmemory;
|
||||
return result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" DLL_EXPORT bool _dbg_getregdump(REGDUMP* regdump)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "console.h"
|
||||
#include "memory.h"
|
||||
#include "sqlhelper.h"
|
||||
#include "breakpoint.h"
|
||||
|
||||
sqlite3* userdb;
|
||||
|
||||
|
@ -20,8 +21,9 @@ void dbinit()
|
|||
dprintf("SQL Error: %s\n", sqllasterror());
|
||||
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 breakpoints (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, addr INT64 NOT NULL, enabled INT NOT NULL, oldbytes INT NOT NULL, type INT NOT NULL)"))
|
||||
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());
|
||||
bpenumall(0);
|
||||
}
|
||||
|
||||
bool dbload()
|
||||
|
@ -43,8 +45,45 @@ void dbclose()
|
|||
}
|
||||
|
||||
///module functions
|
||||
|
||||
static std::vector<MODINFO> modinfo;
|
||||
|
||||
bool modload(uint base, uint size, const char* name)
|
||||
{
|
||||
if(!base or !size or !name or strlen(name)>=31)
|
||||
return false;
|
||||
MODINFO info;
|
||||
info.base=base;
|
||||
info.size=size;
|
||||
strcpy(info.name, name);
|
||||
_strlwr(info.name);
|
||||
modinfo.push_back(info);
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void modclear()
|
||||
{
|
||||
modinfo.clear();
|
||||
}
|
||||
|
||||
bool modnamefromaddr(uint addr, char* modname)
|
||||
{
|
||||
if(!modname)
|
||||
return false;
|
||||
IMAGEHLP_MODULE64 modInfo;
|
||||
memset(&modInfo, 0, sizeof(modInfo));
|
||||
modInfo.SizeOfStruct=sizeof(IMAGEHLP_MODULE64);
|
||||
|
@ -65,6 +104,19 @@ uint modbasefromaddr(uint addr)
|
|||
return modInfo.BaseOfImage;
|
||||
}
|
||||
|
||||
uint modbasefromname(const char* modname)
|
||||
{
|
||||
if(!modname)
|
||||
return 0;
|
||||
int total=modinfo.size();
|
||||
for(int i=0; i<total; i++)
|
||||
{
|
||||
if(!_stricmp(modinfo.at(i).name, modname))
|
||||
return modinfo.at(i).base;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
///api functions
|
||||
bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum)
|
||||
{
|
||||
|
|
|
@ -12,8 +12,8 @@ typedef void (*EXPORTENUMCALLBACK)(uint base, const char* mod, const char* name,
|
|||
//structures
|
||||
struct MODINFO
|
||||
{
|
||||
uint start;
|
||||
uint end;
|
||||
uint base;
|
||||
uint size;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
|
@ -21,8 +21,12 @@ void dbinit();
|
|||
bool dbsave();
|
||||
bool dbload();
|
||||
void dbclose();
|
||||
bool modload(uint base, uint size, const char* name);
|
||||
bool modunload(uint base);
|
||||
void modclear();
|
||||
bool modnamefromaddr(uint addr, char* modname);
|
||||
uint modbasefromaddr(uint addr);
|
||||
uint modbasefromname(const char* modname);
|
||||
bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum);
|
||||
bool commentset(uint addr, const char* text);
|
||||
bool commentget(uint addr, char* text);
|
||||
|
|
|
@ -1,123 +1,227 @@
|
|||
#include "breakpoint.h"
|
||||
#include "debugger.h"
|
||||
#include "addrinfo.h"
|
||||
#include "sqlhelper.h"
|
||||
#include "console.h"
|
||||
|
||||
BREAKPOINT* bpinit()
|
||||
static uint bpaddrs[1000];
|
||||
static int bptitantype[1000];
|
||||
static int bpcount=0;
|
||||
|
||||
int bpgetlist(uint** list, int** type)
|
||||
{
|
||||
BREAKPOINT* bp=(BREAKPOINT*)emalloc(sizeof(BREAKPOINT), "bpinit:bp");
|
||||
memset(bp, 0, sizeof(BREAKPOINT));
|
||||
return bp;
|
||||
if(!list or !type)
|
||||
return bpcount;
|
||||
*list=bpaddrs;
|
||||
*type=bptitantype;
|
||||
return bpcount;
|
||||
}
|
||||
|
||||
void bpfree(BREAKPOINT* breakpoint_list)
|
||||
bool bpnew(uint addr, bool enabled, bool singleshoot, short oldbytes, BP_TYPE type, int titantype)
|
||||
{
|
||||
BREAKPOINT* cur=breakpoint_list;
|
||||
while(cur)
|
||||
{
|
||||
if(cur->name)
|
||||
efree(cur->name, "bpfree:cur->name");
|
||||
BREAKPOINT* next=cur->next;
|
||||
efree(cur, "bpfree:cur");
|
||||
cur=next;
|
||||
}
|
||||
}
|
||||
|
||||
BREAKPOINT* bpfind(BREAKPOINT* breakpoint_list, const char* name, uint addr, BREAKPOINT** link, BP_TYPE type)
|
||||
{
|
||||
BREAKPOINT* cur=breakpoint_list;
|
||||
if(!cur or !cur->addr)
|
||||
return 0;
|
||||
BREAKPOINT* prev=0;
|
||||
while(cur)
|
||||
{
|
||||
BP_TYPE bptype=cur->type;
|
||||
if(bptype==BPSINGLESHOOT)
|
||||
bptype=BPNORMAL;
|
||||
BP_TYPE realtype=type;
|
||||
if(realtype==BPSINGLESHOOT)
|
||||
realtype=BPNORMAL;
|
||||
if(((name and arraycontains(cur->name, name)) or cur->addr==addr) and (type==BPNOTYPE or bptype==realtype))
|
||||
{
|
||||
if(link)
|
||||
*link=prev;
|
||||
return cur;
|
||||
}
|
||||
prev=cur;
|
||||
cur=cur->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool bpnew(BREAKPOINT* breakpoint_list, const char* name, uint addr, short oldbytes, BP_TYPE type)
|
||||
{
|
||||
if(!breakpoint_list or !addr or bpfind(breakpoint_list, name, addr, 0, type))
|
||||
char modname[256]="";
|
||||
if(!modnamefromaddr(addr, modname)) //no module
|
||||
return false;
|
||||
BREAKPOINT* bp;
|
||||
bool nonext=false;
|
||||
if(!breakpoint_list->addr)
|
||||
char sql[256]="";
|
||||
uint modbase=modbasefromaddr(addr);
|
||||
sprintf(sql, "SELECT * FROM breakpoints WHERE addr=%"fext"d AND mod='%s' AND type=%d", addr-modbase, modname, type);
|
||||
if(sqlhasresult(userdb, sql)) //no breakpoint set
|
||||
return false;
|
||||
sprintf(sql, "INSERT INTO breakpoints (addr,enabled,singleshoot,oldbytes,type,titantype,mod) VALUES (%"fext"d,%d,%d,%d,%d,%d,'%s')", addr-modbase, enabled, singleshoot, oldbytes, type, titantype, modname);
|
||||
if(!sqlexec(userdb, sql))
|
||||
{
|
||||
bp=breakpoint_list;
|
||||
nonext=true;
|
||||
dprintf("SQL Error: %s\n", sqllasterror());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
bp=(BREAKPOINT*)emalloc(sizeof(BREAKPOINT), "bpnew:bp");
|
||||
memset(bp, 0, sizeof(BREAKPOINT));
|
||||
if(name and *name)
|
||||
bpenumall(0); //update breakpoint list
|
||||
dbsave();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpget(uint addr, BP_TYPE type, BREAKPOINT* bp)
|
||||
{
|
||||
char sql[256]="";
|
||||
char modname[256]="";
|
||||
if(!modnamefromaddr(addr, modname)) //no module
|
||||
return false;
|
||||
uint modbase=modbasefromaddr(addr);
|
||||
sprintf(sql, "SELECT enabled,singleshoot,oldbytes,type,titantype,name FROM breakpoints WHERE addr=%"fext"d AND type=%d AND mod='%s'", addr-modbase, type, modname);
|
||||
sqlite3_stmt* stmt;
|
||||
if(sqlite3_prepare_v2(userdb, sql, -1, &stmt, 0)!=SQLITE_OK)
|
||||
{
|
||||
bp->name=(char*)emalloc(strlen(name)+1, "bpnew:bp->name");
|
||||
strcpy(bp->name, name);
|
||||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
if(sqlite3_step(stmt)!=SQLITE_ROW)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
if(!bp) //just check if a breakpoint exists
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
return true;
|
||||
}
|
||||
//addr
|
||||
bp->addr=addr;
|
||||
bp->type=type;
|
||||
bp->oldbytes=oldbytes;
|
||||
bp->enabled=true;
|
||||
BREAKPOINT* cur=breakpoint_list;
|
||||
if(!nonext)
|
||||
{
|
||||
while(cur->next)
|
||||
cur=cur->next;
|
||||
cur->next=bp;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpsetname(BREAKPOINT* breakpoint_list, uint addr, const char* name)
|
||||
{
|
||||
//TODO: fix this BPNOTYPE, it's bullshit
|
||||
if(!name or !*name or !addr or bpfind(breakpoint_list, name, 0, 0, BPNOTYPE))
|
||||
return false;
|
||||
BREAKPOINT* found=bpfind(breakpoint_list, 0, addr, 0, BPNOTYPE);
|
||||
if(!found)
|
||||
return false;
|
||||
efree(found->name, "bpsetname:found->name"); //free previous name
|
||||
found->name=(char*)emalloc(strlen(name)+1, "bpsetname:found->name");
|
||||
strcpy(found->name, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpdel(BREAKPOINT* breakpoint_list, const char* name, uint addr, BP_TYPE type)
|
||||
{
|
||||
BREAKPOINT* prev=0;
|
||||
BREAKPOINT* found=bpfind(breakpoint_list, name, addr, &prev, type);
|
||||
if(!found)
|
||||
return false;
|
||||
if(found->name)
|
||||
efree(found->name, "bpdel:found->name");
|
||||
if(found==breakpoint_list)
|
||||
{
|
||||
BREAKPOINT* next=breakpoint_list->next;
|
||||
if(next)
|
||||
{
|
||||
memcpy(breakpoint_list, breakpoint_list->next, sizeof(BREAKPOINT));
|
||||
breakpoint_list->next=next->next;
|
||||
efree(next, "bpdel:next");
|
||||
}
|
||||
else
|
||||
memset(breakpoint_list, 0, sizeof(BREAKPOINT));
|
||||
}
|
||||
//enabled
|
||||
if(sqlite3_column_int(stmt, 0))
|
||||
bp->enabled=true;
|
||||
else
|
||||
{
|
||||
prev->next=found->next;
|
||||
efree(found, "bpdel:found");
|
||||
}
|
||||
bp->enabled=false;
|
||||
//singleshoot
|
||||
if(sqlite3_column_int(stmt, 1))
|
||||
bp->singleshoot=true;
|
||||
else
|
||||
bp->singleshoot=false;
|
||||
//oldbytes
|
||||
bp->oldbytes=(short)(sqlite3_column_int(stmt, 2)&0xFFFF);
|
||||
//type
|
||||
bp->type=(BP_TYPE)sqlite3_column_int(stmt, 3);
|
||||
//titantype
|
||||
bp->titantype=sqlite3_column_int(stmt, 4);
|
||||
//name
|
||||
const char* name=(const char*)sqlite3_column_text(stmt, 5);
|
||||
if(name)
|
||||
strcpy(bp->name, name);
|
||||
else
|
||||
*bp->name=0;
|
||||
sqlite3_finalize(stmt);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpdel(uint addr, BP_TYPE type)
|
||||
{
|
||||
char modname[256]="";
|
||||
if(!modnamefromaddr(addr, modname)) //no module
|
||||
return false;
|
||||
uint modbase=modbasefromaddr(addr);
|
||||
char sql[256]="";
|
||||
sprintf(sql, "SELECT * FROM breakpoints WHERE addr=%"fext"d AND mod='%s' AND type=%d", addr-modbase, modname, type);
|
||||
if(!sqlhasresult(userdb, sql)) //no breakpoint
|
||||
return false;
|
||||
sprintf(sql, "DELETE FROM breakpoints WHERE addr=%"fext"d AND mod='%s' AND type=%d", addr-modbase, modname, type);
|
||||
if(!sqlexec(userdb, sql))
|
||||
{
|
||||
dprintf("SQL Error: %s\n", sqllasterror());
|
||||
return false;
|
||||
}
|
||||
bpenumall(0); //update breakpoint list
|
||||
dbsave();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpenable(uint addr, BP_TYPE type, bool enable)
|
||||
{
|
||||
char modname[256]="";
|
||||
if(!modnamefromaddr(addr, modname)) //no module
|
||||
return false;
|
||||
uint modbase=modbasefromaddr(addr);
|
||||
char sql[256]="";
|
||||
sprintf(sql, "SELECT * FROM breakpoints WHERE addr=%"fext"d AND mod='%s' AND type=%d", addr-modbase, modname, type);
|
||||
if(!sqlhasresult(userdb, sql)) //no breakpoint
|
||||
return false;
|
||||
sprintf(sql, "UPDATE breakpoints SET enabled=%d WHERE addr=%"fext"d AND mod='%s' AND type=%d", enable, addr-modbase, modname, type);
|
||||
if(!sqlexec(userdb, sql))
|
||||
{
|
||||
dprintf("SQL Error: %s\n", sqllasterror());
|
||||
return false;
|
||||
}
|
||||
dbsave();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpsetname(uint addr, BP_TYPE type, const char* name)
|
||||
{
|
||||
if(!name)
|
||||
return false;
|
||||
char modname[256]="";
|
||||
if(!modnamefromaddr(addr, modname)) //no module
|
||||
return false;
|
||||
uint modbase=modbasefromaddr(addr);
|
||||
char sql[256]="";
|
||||
sprintf(sql, "SELECT * FROM breakpoints WHERE addr=%"fext"d AND mod='%s' AND type=%d", addr-modbase, modname, type);
|
||||
if(!sqlexec(userdb, sql))
|
||||
{
|
||||
dprintf("SQL Error: %s\n", sqllasterror());
|
||||
return false;
|
||||
}
|
||||
char bpname[MAX_BREAKPOINT_NAME]="";
|
||||
sqlstringescape(name, bpname);
|
||||
sprintf(sql, "UPDATE breakpoints SET name='%s' WHERE addr=%"fext"d AND mod='%s' AND type=%d", bpname, addr-modbase, modname, type);
|
||||
if(!sqlexec(userdb, sql))
|
||||
{
|
||||
dprintf("SQL Error: %s\n", sqllasterror());
|
||||
return false;
|
||||
}
|
||||
dbsave();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpenumall(BPENUMCALLBACK cbEnum, const char* module)
|
||||
{
|
||||
if(!cbEnum)
|
||||
bpcount=0;
|
||||
char sql[256]="";
|
||||
if(!module)
|
||||
sprintf(sql, "SELECT addr,enabled,singleshoot,oldbytes,type,titantype,mod,name FROM breakpoints");
|
||||
else
|
||||
sprintf(sql, "SELECT addr,enabled,singleshoot,oldbytes,type,titantype,mod,name FROM breakpoints WHERE mod='%s'", module);
|
||||
sqlite3_stmt* stmt;
|
||||
if(sqlite3_prepare_v2(userdb, sql, -1, &stmt, 0)!=SQLITE_OK)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
if(sqlite3_step(stmt)!=SQLITE_ROW)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
BREAKPOINT curbp;
|
||||
do
|
||||
{
|
||||
#ifdef _WIN64
|
||||
uint rva=sqlite3_column_int64(stmt, 0); //addr
|
||||
#else
|
||||
uint rva=sqlite3_column_int(stmt, 0); //addr
|
||||
#endif // _WIN64
|
||||
if(sqlite3_column_int(stmt, 1)) //enabled
|
||||
curbp.enabled=true;
|
||||
else
|
||||
curbp.enabled=false;
|
||||
if(sqlite3_column_int(stmt, 2)) //singleshoot
|
||||
curbp.singleshoot=true;
|
||||
else
|
||||
curbp.singleshoot=false;
|
||||
curbp.oldbytes=(short)(sqlite3_column_int(stmt, 3)&0xFFFF); //oldbytes
|
||||
curbp.type=(BP_TYPE)sqlite3_column_int(stmt, 4); //type
|
||||
curbp.titantype=sqlite3_column_int(stmt, 5); //titantype
|
||||
const char* modname=(const char*)sqlite3_column_text(stmt, 6); //mod
|
||||
const char* bpname=(const char*)sqlite3_column_text(stmt, 7); //name
|
||||
if(bpname)
|
||||
strcpy(curbp.name, bpname);
|
||||
else
|
||||
*curbp.name=0;
|
||||
uint modbase=modbasefromname(modname);
|
||||
if(!modbase) //module not loaded
|
||||
continue;
|
||||
curbp.addr=modbase+rva;
|
||||
if(cbEnum)
|
||||
cbEnum(&curbp);
|
||||
else if(bpcount<1000 and curbp.type==BPNORMAL)
|
||||
{
|
||||
bpaddrs[bpcount]=curbp.addr;
|
||||
bptitantype[bpcount]=curbp.titantype;
|
||||
bpcount++;
|
||||
}
|
||||
}
|
||||
while(sqlite3_step(stmt)==SQLITE_ROW);
|
||||
sqlite3_finalize(stmt);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpenumall(BPENUMCALLBACK cbEnum)
|
||||
{
|
||||
return bpenumall(cbEnum, 0);
|
||||
}
|
||||
|
|
|
@ -4,33 +4,41 @@
|
|||
#include "_global.h"
|
||||
#include "TitanEngine\TitanEngine.h"
|
||||
|
||||
#define MAX_BREAKPOINT_NAME 256
|
||||
|
||||
//enums
|
||||
enum BP_TYPE
|
||||
{
|
||||
BPNORMAL=UE_BREAKPOINT,
|
||||
BPSINGLESHOOT=UE_SINGLESHOOT,
|
||||
BPHARDWARE=UE_HARDWARE,
|
||||
BPMEMORY=UE_MEMORY,
|
||||
BPNOTYPE=-1
|
||||
BPNORMAL,
|
||||
BPHARDWARE,
|
||||
BPMEMORY
|
||||
};
|
||||
|
||||
//structs
|
||||
#pragma pack(1)
|
||||
struct BREAKPOINT
|
||||
{
|
||||
char* name;
|
||||
uint addr;
|
||||
bool enabled;
|
||||
bool singleshoot;
|
||||
short oldbytes;
|
||||
BP_TYPE type;
|
||||
BREAKPOINT* next;
|
||||
int titantype;
|
||||
char name[MAX_BREAKPOINT_NAME];
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
//typedefs
|
||||
typedef void (*BPENUMCALLBACK)(const BREAKPOINT* bp);
|
||||
|
||||
//functions
|
||||
BREAKPOINT* bpinit();
|
||||
void bpfree(BREAKPOINT* breakpoint_list);
|
||||
BREAKPOINT* bpfind(BREAKPOINT* breakpoint_list, const char* name, uint addr, BREAKPOINT** link, BP_TYPE type);
|
||||
bool bpnew(BREAKPOINT* breakpoint_list, const char* name, uint addr, short oldbytes, BP_TYPE type);
|
||||
bool bpsetname(BREAKPOINT* breakpoint_list, uint addr, const char* name);
|
||||
bool bpdel(BREAKPOINT* breakpoint_list, const char* name, uint addr, BP_TYPE type);
|
||||
int bpgetlist(uint** list, int** type);
|
||||
bool bpnew(uint addr, bool enabled, bool singleshoot, short oldbytes, BP_TYPE type, int titantype);
|
||||
bool bpget(uint addr, BP_TYPE type, BREAKPOINT* bp);
|
||||
bool bpdel(uint addr, BP_TYPE type);
|
||||
bool bpenable(uint addr, BP_TYPE type, bool enable);
|
||||
bool bpsetname(uint addr, BP_TYPE type, const char* name);
|
||||
bool bpenumall(BPENUMCALLBACK cbEnum);
|
||||
bool bpenumall(BPENUMCALLBACK cbEnum, const char* module);
|
||||
|
||||
#endif // _BREAKPOINT_H
|
||||
|
|
|
@ -30,36 +30,25 @@ static void cbUserBreakpoint();
|
|||
|
||||
void dbgdisablebpx()
|
||||
{
|
||||
BREAKPOINT* cur=bplist;
|
||||
if(!cur or !cur->addr)
|
||||
return;
|
||||
bool bNext=true;
|
||||
while(bNext)
|
||||
uint* bplist=0;
|
||||
int* titantype=0;
|
||||
int bpcount=bpgetlist(&bplist, &titantype);
|
||||
for(int i=0; i<bpcount; i++)
|
||||
{
|
||||
if(cur->type==BPNORMAL or cur->type==BPSINGLESHOOT)
|
||||
if(IsBPXEnabled(cur->addr) and DeleteBPX(cur->addr))
|
||||
cur->enabled=false;
|
||||
cur=cur->next;
|
||||
if(!cur)
|
||||
bNext=false;
|
||||
//printf(fhex"\n", bplist[i]);
|
||||
if(IsBPXEnabled(bplist[i]))
|
||||
DeleteBPX(bplist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void dbgenablebpx()
|
||||
{
|
||||
BREAKPOINT* cur=bplist;
|
||||
if(!cur or !cur->addr)
|
||||
return;
|
||||
bool bNext=true;
|
||||
while(bNext)
|
||||
{
|
||||
if(cur->type==BPNORMAL or cur->type==BPSINGLESHOOT)
|
||||
if(!IsBPXEnabled(cur->addr) and SetBPX(cur->addr, cur->type, (void*)cbUserBreakpoint))
|
||||
cur->enabled=true;
|
||||
cur=cur->next;
|
||||
if(!cur)
|
||||
bNext=false;
|
||||
}
|
||||
uint* bplist=0;
|
||||
int* titantype=0;
|
||||
int bpcount=bpgetlist(&bplist, &titantype);
|
||||
for(int i=0; i<bpcount; i++)
|
||||
if(!IsBPXEnabled(bplist[i]))
|
||||
SetBPX(bplist[i], titantype[i], (void*)cbUserBreakpoint);
|
||||
}
|
||||
|
||||
bool dbgisrunning()
|
||||
|
@ -77,16 +66,17 @@ void DebugUpdateGui(uint disasm_addr)
|
|||
|
||||
static void cbUserBreakpoint()
|
||||
{
|
||||
BREAKPOINT* cur=bpfind(bplist, 0, (uint)GetContextData(UE_CIP), 0, BPNORMAL);
|
||||
if(!cur)
|
||||
//TODO: restore bp
|
||||
BREAKPOINT bp;
|
||||
if(!bpget(GetContextData(UE_CIP), BPNORMAL, &bp))
|
||||
dputs("breakpoint reached not in list!");
|
||||
else
|
||||
{
|
||||
const char* apiname=(const char*)ImporterGetAPINameFromDebugee(fdProcessInfo->hProcess, cur->addr);
|
||||
const char* apiname=(const char*)ImporterGetAPINameFromDebugee(fdProcessInfo->hProcess, bp.addr);
|
||||
char log[deflen]="";
|
||||
if(apiname)
|
||||
{
|
||||
const char* dllname_=(const char*)ImporterGetDLLNameFromDebugee(fdProcessInfo->hProcess, cur->addr);
|
||||
const char* dllname_=(const char*)ImporterGetDLLNameFromDebugee(fdProcessInfo->hProcess, bp.addr);
|
||||
char dllname[256]="";
|
||||
strcpy(dllname, dllname_);
|
||||
_strlwr(dllname);
|
||||
|
@ -97,21 +87,21 @@ static void cbUserBreakpoint()
|
|||
dllname[i]=0;
|
||||
break;
|
||||
}
|
||||
if(cur->name)
|
||||
sprintf(log, "breakpoint \"%s\" at %s.%s ("fhex")!", cur->name, dllname, apiname, cur->addr);
|
||||
if(*bp.name)
|
||||
sprintf(log, "breakpoint \"%s\" at %s.%s ("fhex")!", bp.name, dllname, apiname, bp.addr);
|
||||
else
|
||||
sprintf(log, "breakpoint at %s.%s ("fhex")!", dllname, apiname, cur->addr);
|
||||
sprintf(log, "breakpoint at %s.%s ("fhex")!", dllname, apiname, bp.addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cur->name)
|
||||
sprintf(log, "breakpoint \"%s\" at "fhex"!", cur->name, cur->addr);
|
||||
if(*bp.name)
|
||||
sprintf(log, "breakpoint \"%s\" at "fhex"!", bp.name, bp.addr);
|
||||
else
|
||||
sprintf(log, "breakpoint at "fhex"!", cur->addr);
|
||||
sprintf(log, "breakpoint at "fhex"!", bp.addr);
|
||||
}
|
||||
dputs(log);
|
||||
if(cur->type==BPSINGLESHOOT)
|
||||
bpdel(bplist, 0, cur->addr, BPNORMAL);
|
||||
if(bp.singleshoot)
|
||||
bpdel(bp.addr, BPNORMAL);
|
||||
}
|
||||
DebugUpdateGui(GetContextData(UE_CIP));
|
||||
GuiSetDebugState(paused);
|
||||
|
@ -122,8 +112,9 @@ static void cbUserBreakpoint()
|
|||
|
||||
static void cbHardwareBreakpoint(void* ExceptionAddress)
|
||||
{
|
||||
//TODO: restore bp
|
||||
uint cip=GetContextData(UE_CIP);
|
||||
BREAKPOINT* cur=bpfind(bplist, 0, (uint)ExceptionAddress, 0, BPHARDWARE);
|
||||
/*BREAKPOINT* cur=bpfind(bplist, 0, (uint)ExceptionAddress, 0, BPHARDWARE);
|
||||
if(!cur)
|
||||
dputs("hardware breakpoint reached not in list!");
|
||||
else
|
||||
|
@ -135,7 +126,7 @@ static void cbHardwareBreakpoint(void* ExceptionAddress)
|
|||
else
|
||||
sprintf(log, "hardware breakpoint "fhex"!", cur->addr);
|
||||
dputs(log);
|
||||
}
|
||||
}*/
|
||||
DebugUpdateGui(cip);
|
||||
GuiSetDebugState(paused);
|
||||
//lock
|
||||
|
@ -148,7 +139,7 @@ static void cbMemoryBreakpoint(void* ExceptionAddress)
|
|||
uint cip=GetContextData(UE_CIP);
|
||||
uint size;
|
||||
uint base=memfindbaseaddr(fdProcessInfo->hProcess, (uint)ExceptionAddress, &size);
|
||||
BREAKPOINT* cur=bpfind(bplist, 0, base, 0, BPMEMORY);
|
||||
/*BREAKPOINT* cur=bpfind(bplist, 0, base, 0, BPMEMORY);
|
||||
if(!cur)
|
||||
dputs("memory breakpoint reached not in list!");
|
||||
else
|
||||
|
@ -162,7 +153,7 @@ static void cbMemoryBreakpoint(void* ExceptionAddress)
|
|||
dputs(log);
|
||||
}
|
||||
if(!(cur->oldbytes>>4)) //is auto-restoring?
|
||||
bpdel(bplist, 0, base, BPMEMORY); //delete from breakpoint list
|
||||
bpdel(bplist, 0, base, BPMEMORY); //delete from breakpoint list*/
|
||||
DebugUpdateGui(cip);
|
||||
GuiSetDebugState(paused);
|
||||
//lock
|
||||
|
@ -255,6 +246,24 @@ SymRegisterCallbackProc64(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void cbSetModuleBreakpoints(const BREAKPOINT* bp)
|
||||
{
|
||||
//TODO: more breakpoint types
|
||||
switch(bp->type)
|
||||
{
|
||||
case BPNORMAL:
|
||||
if(bp->enabled)
|
||||
SetBPX(bp->addr, bp->titantype, (void*)cbUserBreakpoint);
|
||||
break;
|
||||
case BPMEMORY:
|
||||
break;
|
||||
case BPHARDWARE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll)
|
||||
{
|
||||
void* base=LoadDll->lpBaseOfDll;
|
||||
|
@ -265,6 +274,33 @@ static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll)
|
|||
DevicePathToPath(DLLDebugFileName, DLLDebugFileName, deflen);
|
||||
dprintf("DLL Loaded: "fhex" %s\n", base, DLLDebugFileName);
|
||||
SymLoadModuleEx(fdProcessInfo->hProcess, LoadDll->hFile, DLLDebugFileName, 0, (DWORD64)base, 0, 0, 0);
|
||||
IMAGEHLP_MODULE64 modInfo;
|
||||
memset(&modInfo, 0, sizeof(modInfo));
|
||||
modInfo.SizeOfStruct=sizeof(IMAGEHLP_MODULE64);
|
||||
if(SymGetModuleInfo64(fdProcessInfo->hProcess, (DWORD64)base, &modInfo))
|
||||
modload((uint)base, modInfo.ImageSize, modInfo.ModuleName);
|
||||
bpenumall(0);
|
||||
char modname[256]="";
|
||||
if(modnamefromaddr((uint)base, modname))
|
||||
bpenumall(cbSetModuleBreakpoints, modname);
|
||||
}
|
||||
|
||||
static void cbRemoveModuleBreakpoints(const BREAKPOINT* bp)
|
||||
{
|
||||
//TODO: more breakpoint types
|
||||
switch(bp->type)
|
||||
{
|
||||
case BPNORMAL:
|
||||
if(IsBPXEnabled(bp->addr))
|
||||
DeleteBPX(bp->addr);
|
||||
break;
|
||||
case BPMEMORY:
|
||||
break;
|
||||
case BPHARDWARE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void cbUnloadDll(UNLOAD_DLL_DEBUG_INFO* UnloadDll)
|
||||
|
@ -276,7 +312,11 @@ static void cbUnloadDll(UNLOAD_DLL_DEBUG_INFO* UnloadDll)
|
|||
else
|
||||
DevicePathToPath(DLLDebugFileName, DLLDebugFileName, deflen);
|
||||
dprintf("DLL Unloaded: "fhex" %s\n", base, DLLDebugFileName);
|
||||
char modname[256]="";
|
||||
if(modnamefromaddr((uint)base, modname))
|
||||
bpenumall(cbSetModuleBreakpoints, modname);
|
||||
SymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)base);
|
||||
bpenumall(0);
|
||||
}
|
||||
|
||||
static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
|
||||
|
@ -309,6 +349,15 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
|
|||
SymInitialize(fdProcessInfo->hProcess, 0, false); //initialize symbols
|
||||
//SymRegisterCallback64(fdProcessInfo->hProcess, SymRegisterCallbackProc64, 0);
|
||||
SymLoadModuleEx(fdProcessInfo->hProcess, CreateProcessInfo->hFile, DebugFileName, 0, (DWORD64)base, 0, 0, 0);
|
||||
IMAGEHLP_MODULE64 modInfo;
|
||||
memset(&modInfo, 0, sizeof(modInfo));
|
||||
modInfo.SizeOfStruct=sizeof(IMAGEHLP_MODULE64);
|
||||
if(SymGetModuleInfo64(fdProcessInfo->hProcess, (DWORD64)base, &modInfo))
|
||||
modload((uint)base, modInfo.ImageSize, modInfo.ModuleName);
|
||||
bpenumall(0);
|
||||
char modname[256]="";
|
||||
if(modnamefromaddr((uint)base, modname))
|
||||
bpenumall(cbSetModuleBreakpoints, modname);
|
||||
}
|
||||
|
||||
static void cbSystemBreakpoint(void* ExceptionData)
|
||||
|
@ -386,7 +435,6 @@ static DWORD WINAPI threadDebugLoop(void* lpParameter)
|
|||
varset("$hp", (uint)fdProcessInfo->hProcess, true);
|
||||
varset("$pid", fdProcessInfo->dwProcessId, true);
|
||||
ecount=0;
|
||||
bplist=bpinit();
|
||||
//NOTE: set custom handlers
|
||||
SetCustomHandler(UE_CH_CREATEPROCESS, (void*)cbCreateProcess);
|
||||
SetCustomHandler(UE_CH_SYSTEMBREAKPOINT, (void*)cbSystemBreakpoint);
|
||||
|
@ -402,7 +450,6 @@ static DWORD WINAPI threadDebugLoop(void* lpParameter)
|
|||
SymCleanup(fdProcessInfo->hProcess);
|
||||
dbclose();
|
||||
GuiSetDebugState(stopped);
|
||||
bpfree(bplist);
|
||||
dputs("debugging stopped!");
|
||||
varset("$hp", 0, true);
|
||||
varset("$pid", 0, true);
|
||||
|
@ -544,18 +591,15 @@ CMDRESULT cbDebugSetBPX(const char* cmd) //bp addr [,name [,type]]
|
|||
dputs("entry breakpoint will be set automatically");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
uint type=0;
|
||||
BP_TYPE list_type;
|
||||
int type=0;
|
||||
bool singleshoot=false;
|
||||
if(strstr(argtype, "ss"))
|
||||
{
|
||||
type|=UE_SINGLESHOOT;
|
||||
list_type=BPSINGLESHOOT;
|
||||
singleshoot=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
type|=UE_BREAKPOINT;
|
||||
list_type=BPNORMAL;
|
||||
}
|
||||
if(strstr(argtype, "long"))
|
||||
type|=UE_BREAKPOINT_TYPE_LONG_INT3;
|
||||
else if(strstr(argtype, "ud2"))
|
||||
|
@ -563,22 +607,27 @@ CMDRESULT cbDebugSetBPX(const char* cmd) //bp addr [,name [,type]]
|
|||
else if(strstr(argtype, "short"))
|
||||
type|=UE_BREAKPOINT_TYPE_INT3;
|
||||
short oldbytes;
|
||||
BREAKPOINT* found=bpfind(bplist, 0, addr, 0, BPNORMAL);
|
||||
bool found=bpget(addr, BPNORMAL, 0);
|
||||
if(IsBPXEnabled(addr) or !memread(fdProcessInfo->hProcess, (void*)addr, &oldbytes, sizeof(short), 0) or found or !SetBPX(addr, type, (void*)cbUserBreakpoint))
|
||||
{
|
||||
dprintf("error setting breakpoint at "fhex"!\n", addr);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(bpnew(bplist, argname, addr, oldbytes, list_type))
|
||||
if(bpnew(addr, true, singleshoot, oldbytes, BPNORMAL, type))
|
||||
dprintf("breakpoint at "fhex" set!\n", addr);
|
||||
else
|
||||
{
|
||||
dputs("problem setting breakpoint!");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
GuiUpdateAllViews();
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
CMDRESULT cbDebugEnableBPX(const char* cmd)
|
||||
{
|
||||
//TODO: restore bp
|
||||
/*
|
||||
char arg1[deflen]="";
|
||||
if(!argget(cmd, arg1, 0, true)) //enable all breakpoints
|
||||
{
|
||||
|
@ -637,12 +686,14 @@ CMDRESULT cbDebugEnableBPX(const char* cmd)
|
|||
dputs("could not enable breakpoint");
|
||||
else
|
||||
bp->enabled=true;
|
||||
GuiUpdateAllViews();
|
||||
GuiUpdateAllViews();*/
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
CMDRESULT cbDebugDisableBPX(const char* cmd)
|
||||
{
|
||||
//TODO: restore bp
|
||||
/*
|
||||
char arg1[deflen]="";
|
||||
if(!argget(cmd, arg1, 0, true)) //disable all breakpoints
|
||||
{
|
||||
|
@ -701,12 +752,14 @@ CMDRESULT cbDebugDisableBPX(const char* cmd)
|
|||
dputs("could not disable breakpoint");
|
||||
else
|
||||
bp->enabled=false;
|
||||
GuiUpdateAllViews();
|
||||
GuiUpdateAllViews();*/
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
CMDRESULT cbDebugToggleBPX(const char* cmd)
|
||||
{
|
||||
//TODO: restore bp
|
||||
/*
|
||||
char arg1[deflen]="";
|
||||
if(!argget(cmd, arg1, 0, false))
|
||||
return STATUS_ERROR;
|
||||
|
@ -759,67 +812,58 @@ CMDRESULT cbDebugToggleBPX(const char* cmd)
|
|||
}
|
||||
}
|
||||
varset("$res", (uint)disable, false);
|
||||
GuiUpdateAllViews();
|
||||
GuiUpdateAllViews();*/
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static void cbDeleteAllBreakpoints(const BREAKPOINT* bp)
|
||||
{
|
||||
DeleteBPX(bp->addr);
|
||||
bpdel(bp->addr, BPNORMAL);
|
||||
}
|
||||
|
||||
CMDRESULT cbDebugDeleteBPX(const char* cmd)
|
||||
{
|
||||
//TODO: restore bp
|
||||
char arg1[deflen]="";
|
||||
if(!argget(cmd, arg1, 0, true)) //delete all breakpoints
|
||||
{
|
||||
BREAKPOINT* cur=bplist;
|
||||
if(!cur or !cur->addr)
|
||||
if(!bpgetlist(0, 0))
|
||||
{
|
||||
dputs("no breakpoints!");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
bool bNext=true;
|
||||
while(bNext)
|
||||
{
|
||||
BREAKPOINT* next=cur->next;
|
||||
if(cur->type==BPNORMAL or cur->type==BPSINGLESHOOT)
|
||||
{
|
||||
DeleteBPX(cur->addr);
|
||||
bpdel(bplist, 0, cur->addr, BPNORMAL);
|
||||
}
|
||||
cur=next;
|
||||
if(!cur)
|
||||
bNext=false;
|
||||
}
|
||||
//memset(bplist, 0, sizeof(BREAKPOINT));
|
||||
bpenumall(cbDeleteAllBreakpoints);
|
||||
dputs("all breakpoints deleted!");
|
||||
GuiUpdateAllViews();
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
BREAKPOINT* bp=bpfind(bplist, arg1, 0, 0, BPNORMAL);
|
||||
if(!bp)
|
||||
BREAKPOINT bp;
|
||||
uint addr=0;
|
||||
if(!valfromstring(arg1, &addr, 0, 0, false, 0))
|
||||
{
|
||||
uint addr=0;
|
||||
if(!valfromstring(arg1, &addr, 0, 0, false, 0))
|
||||
{
|
||||
dprintf("invalid addr: \"%s\"\n", arg1);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
bp=bpfind(bplist, 0, addr, 0, BPNORMAL);
|
||||
if(!bp)
|
||||
{
|
||||
dprintf("no such breakpoint: \"%s\"\n", arg1);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
if(!DeleteBPX(bp->addr))
|
||||
{
|
||||
dprintf("delete breakpoint failed: "fhex"\n", bp->addr);
|
||||
dprintf("invalid addr: \"%s\"\n", arg1);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
bpdel(bplist, 0, bp->addr, BPNORMAL);
|
||||
if(!bpget(addr, BPNORMAL, &bp))
|
||||
{
|
||||
dprintf("no such breakpoint: \"%s\"\n", arg1);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
if(!DeleteBPX(bp.addr))
|
||||
{
|
||||
dprintf("delete breakpoint failed: "fhex"\n", bp.addr);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
bpdel(addr, BPNORMAL);
|
||||
GuiUpdateAllViews();
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
CMDRESULT cbDebugBplist(const char* cmd)
|
||||
{
|
||||
//TODO: restore bp
|
||||
/*
|
||||
BREAKPOINT* cur=bplist;
|
||||
if(!cur or !cur->addr)
|
||||
{
|
||||
|
@ -846,7 +890,7 @@ CMDRESULT cbDebugBplist(const char* cmd)
|
|||
cur=cur->next;
|
||||
if(!cur)
|
||||
bNext=false;
|
||||
}
|
||||
}*/
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -901,6 +945,8 @@ CMDRESULT cbDebugDisasm(const char* cmd)
|
|||
|
||||
CMDRESULT cbDebugMemoryBpx(const char* cmd)
|
||||
{
|
||||
//TODO: restore bp
|
||||
/*
|
||||
char arg1[deflen]=""; //addr
|
||||
if(!argget(cmd, arg1, 0, false))
|
||||
return STATUS_ERROR;
|
||||
|
@ -951,7 +997,7 @@ CMDRESULT cbDebugMemoryBpx(const char* cmd)
|
|||
dprintf("memory breakpoint at "fhex" set!\n", addr);
|
||||
else
|
||||
dputs("problem setting breakpoint (report please)!");
|
||||
GuiUpdateAllViews();
|
||||
GuiUpdateAllViews();*/
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -964,6 +1010,8 @@ CMDRESULT cbDebugRtr(const char* cmd)
|
|||
|
||||
CMDRESULT cbDebugSetHardwareBreakpoint(const char* cmd)
|
||||
{
|
||||
//TODO: restore bp
|
||||
/*
|
||||
char arg1[deflen]=""; //addr
|
||||
if(!argget(cmd, arg1, 0, false))
|
||||
return STATUS_ERROR;
|
||||
|
@ -1003,11 +1051,11 @@ CMDRESULT cbDebugSetHardwareBreakpoint(const char* cmd)
|
|||
case 4:
|
||||
size=UE_HARDWARE_SIZE_4;
|
||||
break;
|
||||
#ifdef _WIN64
|
||||
#ifdef _WIN64
|
||||
case 8:
|
||||
size=UE_HARDWARE_SIZE_8;
|
||||
break;
|
||||
#endif // _WIN64
|
||||
#endif // _WIN64
|
||||
default:
|
||||
dputs("invalid size, using 1");
|
||||
break;
|
||||
|
@ -1034,7 +1082,7 @@ CMDRESULT cbDebugSetHardwareBreakpoint(const char* cmd)
|
|||
dprintf("hardware breakpoint at "fhex" set!\n", addr);
|
||||
else
|
||||
dputs("problem setting breakpoint (report please)!");
|
||||
GuiUpdateAllViews();
|
||||
GuiUpdateAllViews();*/
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -288,6 +288,7 @@ CMDRESULT cbLoaddb(const char* cmd)
|
|||
puts("failed to load database from disk!");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
GuiUpdateAllViews();
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,13 +29,13 @@ bool sqlhasresult(sqlite3* db, const char* query)
|
|||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
if(sqlite3_step(stmt)==SQLITE_ROW) //there is a label already
|
||||
if(sqlite3_step(stmt)!=SQLITE_ROW)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sqlgettext(sqlite3* db, const char* query, char* result)
|
||||
|
@ -48,7 +48,7 @@ bool sqlgettext(sqlite3* db, const char* query, char* result)
|
|||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
if(sqlite3_step(stmt)!=SQLITE_ROW) //there is a label already
|
||||
if(sqlite3_step(stmt)!=SQLITE_ROW)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
|
@ -68,7 +68,7 @@ bool sqlgetint(sqlite3* db, const char* query, int* result)
|
|||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
if(sqlite3_step(stmt)!=SQLITE_ROW) //there is a label already
|
||||
if(sqlite3_step(stmt)!=SQLITE_ROW)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
|
@ -88,7 +88,7 @@ bool sqlgetuint(sqlite3* db, const char* query, uint* result)
|
|||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
if(sqlite3_step(stmt)!=SQLITE_ROW) //there is a label already
|
||||
if(sqlite3_step(stmt)!=SQLITE_ROW)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue