ultimatepp/uppsrc/ide/Debuggers/Code.cpp
cxl 331da1076f Minor fixes
git-svn-id: svn://ultimatepp.org/upp/trunk@1106 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2009-04-27 17:48:02 +00:00

447 lines
8 KiB
C++

#include "Debuggers.h"
#ifdef COMPILER_MSC
#define LLOG(x) // LOG(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;
}
int sz = NDisassemble(out, code, ip);
if(sz > i)
return -1;
disas.Add(ip, out, Null);
return sz;
}
void Pdb::Reg(Label& reg, adr_t val)
{
String h = Sprintf("%08X", val);
if(h != reg.GetText()) {
reg.SetLabel(h);
reg.SetInk(LtRed);
}
else
reg.SetInk(SColorText);
}
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;
}
void Pdb::Sync0()
{
stop = false;
const CONTEXT& context = threads.Get((int)~threadlist).context;
#ifdef CPU_32
adr_t eip = context.Eip;
adr_t ebp = context.Ebp;
#else
adr_t eip = context.Rip;
adr_t ebp = context.Rbp;
#endif
adr_t spmax = threads.Get(event.dwThreadId).sp;
framelist.Clear();
frame.Clear();
int ndx = 0;
FnInfo fn = GetFnInfo(eip);
int c = -1;
for(;;) {
Frame& f = frame.Add();
f.reip = eip;
f.rebp = ebp;
f.fn = fn;
String r;
if(IsNull(fn.name)) {
r = Sprintf("0x%08x", f.reip);
for(int i = 0; i < module.GetCount(); i++) {
const ModuleInfo& f = module[i];
if(eip >= f.base && eip < f.base + f.size) {
r << " (" << GetFileName(f.path) << ")";
break;
}
}
}
else {
GetLocals(eip, ebp, f.param, f.local);
r = fn.name;
r << '(';
for(int i = 0; i < f.param.GetCount(); i++) {
if(i)
r << ", ";
r << f.param.GetKey(i) << "=" << Visualise(f.param[i]).GetString();
}
r << ')';
if(c < 0)
c = frame.GetCount() - 1;
}
framelist.Add(frame.GetCount() - 1, r);
int q = 0;
for(;;) {
if(ebp > spmax || ++q > 1024 * 64)
goto end;
adr_t neip, nebp;
if(!Copy(ebp, &nebp, 4))
goto end;
if(!Copy(ebp + 4, &neip, 4))
goto end;
if(nebp >= ebp && nebp < spmax && IsValidFrame(neip)) {
fn = GetFnInfo(neip);
if(!IsNull(fn.name)) {
eip = neip;
ebp = nebp;
break;
}
}
ebp += 4;
}
}
end:
framelist <<= max(c, 0);
}
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 q = ~framelist;
if(q >= 0 && q < frame.GetCount()) {
Frame& f = frame[q];
Image ptrimg = q == 0 ? DbgImg::IpLinePtr() : DbgImg::FrameLinePtr();
bool df = disas.HasFocus();
FilePos fp = GetFilePos(f.reip);
IdeHidePtr();
autotext.Clear();
if(fp) {
IdeSetDebugPos(fp.path, fp.line, ptrimg, 0);
autotext = IdeGetLine(fp.line - 1) + ' ' + IdeGetLine(fp.line)
+ ' ' + IdeGetLine(fp.line + 1);
}
if(!disas.InRange(f.reip) || 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.reip < ip || f.reip >= h) {
ip = f.reip;
h = ip + 1024;
}
while(ip < h) {
int q = Disassemble(ip);
if(q < 0)
break;
ip += q;
}
}
disas.SetCursor(f.reip);
disas.SetIp(f.reip, ptrimg);
const CONTEXT& context = threads.Get((int)~threadlist).context;
#ifdef CPU_32
Reg(regs.eax, context.Eax);
Reg(regs.ebx, context.Ebx);
Reg(regs.ecx, context.Ecx);
Reg(regs.edx, context.Edx);
Reg(regs.esi, context.Esi);
Reg(regs.edi, context.Edi);
Reg(regs.ebp, context.Ebp);
Reg(regs.esp, context.Esp);
#else
Reg(regs.eax, context.Rax);
Reg(regs.ebx, context.Rbx);
Reg(regs.ecx, context.Rcx);
Reg(regs.edx, context.Rdx);
Reg(regs.esi, context.Rsi);
Reg(regs.edi, context.Rdi);
Reg(regs.ebp, context.Rbp);
Reg(regs.esp, context.Rsp);
#endif
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()
{
adr_t a = CursorAdr();
if(!a)
return false;
if(!SingleStep())
return false;
#ifdef CPU_32
if(context.Eip != a) {
#else
if(context.Rip != a) {
#endif
SetBreakpoints();
AddBp(a);
if(!Continue())
return false;
}
Sync();
return true;
}
void Pdb::Run()
{
SingleStep();
SetBreakpoints();
if(!Continue())
return;
Sync();
}
void Pdb::SetIp()
{
adr_t a = CursorAdr();
if(!a)
return;
#ifdef CPU_32
context.Eip = a;
#else
context.Rip = a;
#endif
WriteContext();
frame[0].reip = a;
framelist <<= 0;
SetFrame();
}
bool Pdb::Step(bool over)
{
TimeStop ts;
#ifdef CPU_32
byte b = Byte(context.Eip);
byte b1 = (Byte(context.Eip + 1) >> 3) & 7;
#else
byte b = Byte(context.Rip);
byte b1 = (Byte(context.Rip + 1) >> 3) & 7;
#endif
if(b == 0xe8 || b == 0x9a || b == 0xff && (b1 == 2 || b1 == 3)) {
if(over) {
int l = 5;
if(b != 0xe8) {
char out[256];
byte code[32];
memset(code, 0, 32);
for(int i = 0; i < 32; i++) {
#ifdef CPU_32
int q = Byte(context.Eip + i);
#else
int q = Byte(context.Rip + i);
#endif
if(q < 0)
break;
code[i] = q;
}
#ifdef CPU_32
l = NDisassemble(out, code, context.Eip);
#else
l = NDisassemble(out, code, context.Rip);
#endif
}
#ifdef CPU_32
adr_t bp0 = context.Eip;
adr_t bp = context.Eip + l;
#else
adr_t bp0 = context.Rip;
adr_t bp = context.Rip + l;
#endif
int lvl = 0;
Lock();
for(;;) {
if(!SingleStep()) {
Unlock();
return false;
}
SetBreakpoints();
if(breakpoint.Find(bp0) < 0)
AddBp(bp0);
else
bp0 = 0;
AddBp(bp);
if(!Continue()) {
Unlock();
return false;
}
#ifdef CPU_32
if(context.Eip == bp0)
#else
if(context.Rip == bp0)
#endif
lvl++;
else
#ifdef CPU_32
if(context.Eip == bp) {
#else
if(context.Rip == bp) {
#endif
if(lvl <= 0) {
Unlock();
return true;
}
lvl--;
}
else {
Unlock();
return true;
}
if(ts.Elapsed() > 100)
Ctrl::ProcessEvents();
}
}
else {
if(!SingleStep())
return false;
#ifdef CPU_32
byte b = Byte(context.Eip);
#else
byte b = Byte(context.Rip);
#endif
if(b == 0xeb || b == 0xe9)
return SingleStep();
return true;
}
}
else
return SingleStep();
}
void Pdb::Trace(bool over)
{
#ifdef CPU_32
adr_t ip0 = context.Eip;
#else
adr_t ip0 = context.Rip;
#endif
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;
#ifdef CPU_32
FilePos p = GetFilePos(context.Eip);
if(context.Eip < ip0 || p.path != p0.path || p.line != p0.line || stop) {
#else
FilePos p = GetFilePos(context.Rip);
if(context.Rip < ip0 || p.path != p0.path || p.line != p0.line || stop) {
#endif
Sync();
break;
}
}
if(locked)
Unlock();
}
void Pdb::StepOut()
{
Lock();
TimeStop ts;
for(;;) {
#ifdef CPU_32
if(Byte(context.Eip) == 0xc2 || Byte(context.Eip) == 0xc3) {
#else
if(Byte(context.Rip) == 0xc2 || Byte(context.Rip) == 0xc3) {
#endif
if(!SingleStep())
break;
Sync();
break;
}
if(stop) {
Sync();
break;
}
if(!Step(true))
break;
if(ts.Elapsed() > 100)
Ctrl::ProcessEvents();
}
Unlock();
}
#endif