mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
340 lines
5.9 KiB
C++
340 lines
5.9 KiB
C++
#include "Debuggers.h"
|
|
|
|
#ifdef COMPILER_MSC
|
|
|
|
#define LLOG(x) // DLOG(x)
|
|
|
|
int Pdb::Disassemble(adr_t ip)
|
|
{
|
|
char out[256];
|
|
byte code[32];
|
|
memset(code, 0, 32);
|
|
int i;
|
|
for(i = 0; i < 32; i++) {
|
|
int q = Byte(i + ip);
|
|
if(q < 0)
|
|
break;
|
|
code[i] = q;
|
|
}
|
|
#ifdef CPU_64
|
|
int sz = NDisassemble(out, code, ip, win64);
|
|
#else
|
|
int sz = NDisassemble(out, code, ip);
|
|
#endif
|
|
if(sz > i)
|
|
return -1;
|
|
disas.Add(ip, out, Null, String(code, sz));
|
|
CParser p(out);
|
|
while(!p.IsEof()) {
|
|
try {
|
|
if(p.Char2('0', 'x'))
|
|
disas.AddT((adr_t)p.ReadNumber64(16));
|
|
}
|
|
catch(CParser::Error) {}
|
|
p.SkipTerm();
|
|
}
|
|
return sz;
|
|
}
|
|
|
|
bool Pdb::IsValidFrame(adr_t eip)
|
|
{
|
|
for(int i = 0; i < module.GetCount(); i++) {
|
|
const ModuleInfo& f = module[i];
|
|
if(eip >= f.base && eip < f.base + f.size)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
adr_t Pdb::GetIP()
|
|
{
|
|
#ifdef CPU_64
|
|
if(win64)
|
|
return context.context64.Rip;
|
|
#endif
|
|
return context.context32.Eip;
|
|
}
|
|
|
|
void Pdb::Sync()
|
|
{
|
|
threadlist.Clear();
|
|
for(int i = 0; i < threads.GetCount(); i++) {
|
|
int thid = threads.GetKey(i);
|
|
AttrText x(Format("0x%x", thid));
|
|
if(thid == event.dwThreadId)
|
|
x.font = StdFont().Bold();
|
|
threadlist.Add(thid, x);
|
|
}
|
|
threadlist <<= (int)event.dwThreadId;
|
|
Sync0();
|
|
SetFrame();
|
|
IdeActivateBottom();
|
|
}
|
|
|
|
void Pdb::SetThread()
|
|
{
|
|
Sync0();
|
|
SetFrame();
|
|
IdeActivateBottom();
|
|
}
|
|
|
|
void Pdb::SetFrame()
|
|
{
|
|
int fi = ~framelist;
|
|
if(fi >= 0 && fi < frame.GetCount()) {
|
|
Frame& f = frame[fi];
|
|
bool df = disas.HasFocus();
|
|
FilePos fp = GetFilePos(f.pc);
|
|
IdeHidePtr();
|
|
autotext.Clear();
|
|
Image ptrimg = fi == 0 ? DbgImg::IpLinePtr() : DbgImg::FrameLinePtr();
|
|
if(fp) {
|
|
IdeSetDebugPos(fp.path, fp.line, ptrimg, 0);
|
|
autotext.Clear();
|
|
for(int i = -4; i < 4; i++)
|
|
autotext << ' ' << IdeGetLine(fp.line + i);
|
|
}
|
|
if(!disas.InRange(f.pc) || f.fn.name != disas_name) {
|
|
disas_name = f.fn.name;
|
|
disas.Clear();
|
|
adr_t ip = f.fn.address;
|
|
adr_t h = f.fn.address + f.fn.size;
|
|
if(f.pc < ip || f.pc >= h) {
|
|
ip = f.pc - 64;
|
|
h = ip + 1024;
|
|
}
|
|
while(ip < h) {
|
|
int sz = Disassemble(ip);
|
|
if(sz < 0)
|
|
break;
|
|
ip += sz;
|
|
}
|
|
}
|
|
disas.SetCursor(f.pc);
|
|
disas.SetIp(f.pc, ptrimg);
|
|
|
|
if(df)
|
|
disas.SetFocus();
|
|
Data();
|
|
}
|
|
}
|
|
|
|
bool Pdb::SetBreakpoint(const String& filename, int line, const String& bp)
|
|
{
|
|
adr_t a = GetAddress(FilePos(filename, line));
|
|
if(!a)
|
|
return false;
|
|
int q = breakpoint.Find(a);
|
|
if(bp.IsEmpty()) {
|
|
if(q >= 0) {
|
|
if(!RemoveBp(a))
|
|
return false;
|
|
breakpoint.Remove(q);
|
|
}
|
|
}
|
|
else {
|
|
if(q < 0) {
|
|
if(!AddBp(a))
|
|
return false;
|
|
breakpoint.Add(a);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
adr_t Pdb::CursorAdr()
|
|
{
|
|
adr_t a = disas.HasFocus() ? disas.GetCursor() : GetAddress(FilePos(IdeGetFileName(), IdeGetFileLine()));
|
|
if(!a)
|
|
Exclamation("No code at choosen location !");
|
|
return a;
|
|
}
|
|
|
|
bool Pdb::RunTo()
|
|
{
|
|
LLOG("== RunTo");
|
|
adr_t a = CursorAdr();
|
|
if(!a)
|
|
return false;
|
|
if(!SingleStep())
|
|
return false;
|
|
if(GetIP() != a) {
|
|
SetBreakpoints();
|
|
AddBp(a);
|
|
if(!Continue())
|
|
return false;
|
|
}
|
|
Sync();
|
|
return true;
|
|
}
|
|
|
|
void Pdb::Run()
|
|
{
|
|
LLOG("== Run");
|
|
SingleStep();
|
|
SetBreakpoints();
|
|
if(!Continue()) {
|
|
LLOG("Run: !Continue");
|
|
return;
|
|
}
|
|
LLOG("Run: Sync");
|
|
Sync();
|
|
}
|
|
|
|
void Pdb::SetIp()
|
|
{
|
|
adr_t a = CursorAdr();
|
|
if(!a)
|
|
return;
|
|
#ifdef CPU_64
|
|
if(win64)
|
|
context.context64.Rip = a;
|
|
else
|
|
#endif
|
|
context.context32.Eip = (DWORD)a;
|
|
WriteContext();
|
|
frame[0].pc = a;
|
|
framelist <<= 0;
|
|
SetFrame();
|
|
}
|
|
|
|
bool Pdb::Step(bool over)
|
|
{
|
|
LLOG("== Step over: " << over);
|
|
TimeStop ts;
|
|
adr_t ip = GetIP();
|
|
byte b = Byte(ip);
|
|
byte b1 = (Byte(ip + 1) >> 3) & 7;
|
|
if(b == 0xe8 || b == 0x9a || b == 0xff && (b1 == 2 || b1 == 3)) { // Various CALL forms
|
|
LLOG("Stepping over CALL");
|
|
if(over) {
|
|
int l = 5;
|
|
if(b != 0xe8) {
|
|
char out[256];
|
|
byte code[32];
|
|
memset(code, 0, 32);
|
|
adr_t ip = GetIP();
|
|
for(int i = 0; i < 32; i++) {
|
|
int q = Byte(ip + i);
|
|
if(q < 0)
|
|
break;
|
|
code[i] = q;
|
|
}
|
|
#ifdef CPU_64
|
|
l = NDisassemble(out, code, GetIP(), win64);
|
|
#else
|
|
l = NDisassemble(out, code, GetIP());
|
|
#endif
|
|
}
|
|
adr_t bp0 = GetIP();
|
|
adr_t bp = bp0 + l;
|
|
int lvl = 0;
|
|
Lock();
|
|
for(;;) {
|
|
if(!SingleStep()) { // Step into function
|
|
Unlock();
|
|
return false;
|
|
}
|
|
SetBreakpoints(); // Note: Do we really want to do this? (activates breakpoints)
|
|
if(breakpoint.Find(bp0) < 0)
|
|
AddBp(bp0);
|
|
else
|
|
bp0 = 0;
|
|
AddBp(bp);
|
|
if(!Continue()) {
|
|
Unlock();
|
|
return false;
|
|
}
|
|
if(GetIP() == bp0)
|
|
lvl++; // Recursive call
|
|
else
|
|
if(GetIP() == bp) {
|
|
if(lvl <= 0) {
|
|
Unlock(); // Base level - stepping ended
|
|
return true;
|
|
}
|
|
lvl--;
|
|
}
|
|
else {
|
|
Unlock(); // Any other breakpoint
|
|
return true;
|
|
}
|
|
if(ts.Elapsed() > 100)
|
|
Ctrl::ProcessEvents();
|
|
}
|
|
}
|
|
else {
|
|
if(!SingleStep())
|
|
return false;
|
|
byte b = Byte(GetIP());
|
|
if(b == 0xeb || b == 0xe9) // Step over JMP following CALL (windows jump tables)
|
|
return SingleStep();
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
return SingleStep();
|
|
}
|
|
|
|
void Pdb::Trace(bool over)
|
|
{
|
|
LLOG("== Trace over: " << over);
|
|
adr_t ip0 = GetIP();
|
|
FilePos p0 = GetFilePos(ip0);
|
|
if(IsNull(p0.path) || disas.HasFocus()) {
|
|
if(!Step(over))
|
|
return;
|
|
Sync();
|
|
return;
|
|
}
|
|
bool locked = false;
|
|
int n = 0;
|
|
TimeStop ts;
|
|
for(;;) {
|
|
if(ts.Elapsed() > 100) {
|
|
if(!locked) {
|
|
Lock();
|
|
locked = true;
|
|
}
|
|
ProcessEvents();
|
|
}
|
|
if(!Step(over))
|
|
break;
|
|
|
|
adr_t ip = GetIP();
|
|
FilePos p = GetFilePos(ip);
|
|
if(ip < ip0 || p.path != p0.path || p.line != p0.line || stop) {
|
|
Sync();
|
|
break;
|
|
}
|
|
}
|
|
if(locked)
|
|
Unlock();
|
|
}
|
|
|
|
void Pdb::StepOut()
|
|
{
|
|
LLOG("== StepOut");
|
|
Lock();
|
|
TimeStop ts;
|
|
for(;;) {
|
|
adr_t ip = GetIP();
|
|
if(Byte(ip) == 0xc2 || Byte(ip) == 0xc3) {
|
|
if(!SingleStep())
|
|
break;
|
|
Sync();
|
|
break;
|
|
}
|
|
if(stop) {
|
|
Sync();
|
|
break;
|
|
}
|
|
if(!Step(true))
|
|
break;
|
|
if(ts.Elapsed() > 100)
|
|
Ctrl::ProcessEvents();
|
|
}
|
|
Unlock();
|
|
}
|
|
|
|
#endif
|