#include "Debuggers.h" #ifdef COMPILER_MSC #pragma comment(lib, "DbgHelp.lib") #pragma comment(lib, "psapi.lib") #define LLOG(x) // LOG(x) #define KEYGROUPNAME "PdbDebugger" #define KEYNAMESPACE PdbKeys #define KEYFILE #include using namespace PdbKeys; void Pdb::DebugBar(Bar& bar) { bar.Add(AK_STOP, THISBACK(Stop)); bool b = !IdeIsDebugLock(); bar.Separator(); bar.Add(b, AK_STEPINTO, DbgImg::StepInto(), THISBACK1(Trace, false)); bar.Add(b, AK_STEPOVER, DbgImg::StepOver(), THISBACK1(Trace, true)); bar.Add(b, AK_STEPOUT, DbgImg::StepOut(), THISBACK(StepOut)); bar.Add(b, AK_RUNTO, DbgImg::RunTo(), THISBACK(DoRunTo)); bar.Add(b, AK_RUN, DbgImg::Run(), THISBACK(Run)); bar.Add(b, AK_SETIP, DbgImg::SetIp(), THISBACK(SetIp)); bar.Add(!b, AK_STOP, DbgImg::Stop(), THISBACK(BreakRunning)); bar.MenuSeparator(); bar.Add(b, AK_AUTOS, THISBACK1(SetTab, 0)); bar.Add(b, AK_LOCALS, THISBACK1(SetTab, 1)); bar.Add(b, AK_WATCHES, THISBACK1(SetTab, 2)); bar.Add(b, AK_ADDWATCH, THISBACK(AddWatch)); bar.Add(b, AK_EXPLORER, THISBACK(DoExplorer)); bar.Add(b, AK_MEMORY, THISBACK1(SetTab, 4)); bar.MenuSeparator(); bar.Add(b, "Copy backtrace", THISBACK(CopyStack)); bar.Add(b, "Copy dissassembly", THISBACK(CopyDisas)); } void Pdb::Tab() { switch(tab.Get()) { case 0: autos.SetFocus(); break; case 1: locals.SetFocus(); break; case 2: watches.SetFocus(); break; case 3: explorer.SetFocus(); break; case 4: memory.SetFocus(); break; } Data(); } bool Pdb::Key(dword key, int count) { if(key >= 32 && key < 65535 && tab.Get() == 2) { watches.DoInsertAfter(); Ctrl* f = GetFocusCtrl(); if(f && watches.HasChildDeep(f)) f->Key(key, count); return true; } if(key == K_ENTER && expexp.HasFocus()) { Explore(~expexp); return true; } return Ctrl::Key(key, count); } #define CONFIGNAME "pdb debugger" void Pdb::Serialize(Stream& s) { int version = 0; s / version; memory.SerializeSettings(s); s % split; } INITBLOCK { RegisterGlobalConfig(CONFIGNAME); } bool Pdb::Create(One local, const String& exefile, const String& cmdline) { STARTUPINFO si; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = 0; String cl; if(exefile.Find(' ') >= 0) cl << '\"' << exefile << '\"'; else cl << exefile; if(!IsNull(cmdline)) cl << ' ' << cmdline; Buffer cmd(cl.GetLength() + 1); memcpy(cmd, cl, cl.GetLength() + 1); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); Buffer env(local->GetEnvironment().GetCount() + 1); memcpy(env, ~local->GetEnvironment(), local->GetEnvironment().GetCount() + 1); bool h = CreateProcess(exefile, cmd, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE|DEBUG_ONLY_THIS_PROCESS, ~env, NULL, &si, &pi); if(!h) { Exclamation("Error creating process&[* " + DeQtf(exefile) + "]"); return false; } hProcess = pi.hProcess; CloseHandle(pi.hThread); IdeSetBottom(*this); IdeSetRight(disas); LoadFromGlobal(*this, CONFIGNAME); if(!SymInitialize(hProcess, 0, FALSE)) { Error(); return false; } SymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_UNDNAME|SYMOPT_NO_UNQUALIFIED_LOADS); lock = 0; stop = false; refreshmodules = true; terminated = false; running = true; RunToException(); // Sync(); return true; } Pdb::Pdb() { hProcess = INVALID_HANDLE_VALUE; CtrlLayout(regs); regs.Height(regs.GetLayoutSize().cy); AddReg("eax", ®s.eax); AddReg("ebx", ®s.ebx); AddReg("ecx", ®s.ecx); AddReg("edx", ®s.edx); AddReg("esi", ®s.esi); AddReg("edi", ®s.edi); AddReg("ebp", ®s.ebp); AddReg("esp", ®s.esp); regs.Color(SColorLtFace); regs.AddFrame(TopSeparatorFrame()); regs.AddFrame(RightSeparatorFrame()); locals.NoHeader(); locals.AddColumn("", 1); locals.AddColumn("", 6).SetDisplay(Single()); locals.WhenEnterRow = THISBACK1(SetTreeA, &locals); locals.WhenBar = THISBACK(LocalsMenu); locals.WhenLeftDouble = THISBACK1(ExploreKey, &locals); watches.NoHeader(); watches.AddColumn("", 1).Edit(watchedit); watches.AddColumn("", 6).SetDisplay(Single()); watches.Inserting().Removing(); watches.WhenEnterRow = THISBACK1(SetTreeA, &watches); watches.WhenBar = THISBACK(WatchesMenu); watches.WhenLeftDouble = THISBACK1(ExploreKey, &watches); autos.NoHeader(); autos.AddColumn("", 1); autos.AddColumn("", 6).SetDisplay(Single()); autos.WhenEnterRow = THISBACK1(SetTreeA, &autos); autos.WhenBar = THISBACK(AutosMenu); autos.WhenLeftDouble = THISBACK1(ExploreKey, &autos); int c = EditField::GetStdHeight(); explorer.AddColumn("", 1); explorer.AddColumn("", 6).SetDisplay(Single()); explorer_pane.Add(exback.LeftPos(0, c).TopPos(0, c)); explorer_pane.Add(exfw.LeftPos(c + 2, c).TopPos(0, c)); explorer_pane.Add(expexp.HSizePos(2 * c + 4).TopPos(0, c)); explorer_pane.Add(explorer.HSizePos().VSizePos(EditField::GetStdHeight(), 0)); explorer.NoHeader(); explorer.WhenEnterRow = THISBACK(ExplorerTree); explorer.WhenLeftDouble = THISBACK(ExpExp); explorer.WhenBar = THISBACK(ExplorerMenu); exback.SetImage(DbgImg::ExplorerBack()); exback <<= THISBACK(ExBack); exfw.SetImage(DbgImg::ExplorerFw()); exfw <<= THISBACK(ExFw); exback.Disable(); exfw.Disable(); tab.Add(autos.SizePos(), "Autos"); tab.Add(locals.SizePos(), "Locals"); tab.Add(watches.SizePos(), "Watches"); tab.Add(explorer_pane.SizePos(), "Explorer"); memory.cdb = this; tab.Add(memory.SizePos(), "Memory"); dlock = " Running.."; dlock.SetFrame(BlackFrame()); dlock.SetInk(Red); dlock.NoTransparent(); dlock.Hide(); framelist.Ctrl::Add(dlock.SizePos()); pane.Add(tab.SizePos()); pane.Add(threadlist.LeftPosZ(320, 60).TopPos(2, EditField::GetStdHeight())); pane.Add(framelist.HSizePosZ(384, 0).TopPos(2, EditField::GetStdHeight())); split.Horz(pane, tree.SizePos()); split.SetPos(8000); Add(split); disas.AddFrame(regs); disas.WhenCursor = THISBACK(DisasCursor); disas.WhenFocus = THISBACK(DisasFocus); memory.WhenGoto = THISBACK(MemoryGoto); tab <<= THISBACK(Tab); framelist <<= THISBACK(SetFrame); threadlist <<= THISBACK(SetThread); watches.WhenAcceptEdit = THISBACK(Data); tab <<= THISBACK(Data); tree.WhenOpen = THISBACK(TreeExpand); FileIn in(ConfigFile("TreeTypes.txt")); while(!in.IsEof()) { String type = in.GetLine(); String desc = in.GetLine(); treetype.Add(type, desc); } } void Pdb::CleanupOnExit() { if(hProcess != INVALID_HANDLE_VALUE) { while(threads.GetCount()) RemoveThread(threads.GetKey(0)); UnloadModuleSymbols(); SymCleanup(hProcess); CloseHandle(hProcess); hProcess = INVALID_HANDLE_VALUE; } } void Pdb::CopyStack() { String s; for(int i = 0; i < framelist.GetCount(); i++) s << framelist.GetValue(i) << "\n"; WriteClipboardText(s); } void Pdb::CopyDisas() { disas.WriteClipboard(); } Pdb::~Pdb() { SaveTree(); String fn = ConfigFile("TreeTypes.txt"); FileOut out(fn); for(int i = 0; i < treetype.GetCount(); i++) out << treetype.GetKey(i) << "\r\n" << treetype[i] << "\r\n"; if(hProcess != INVALID_HANDLE_VALUE) { if(!running) ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); TerminateProcess(hProcess, -1); do { if(!WaitForDebugEvent(&event, INFINITE)) break; if(!ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE)) break; } while(event.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT); CleanupOnExit(); } StoreToGlobal(*this, CONFIGNAME); IdeRemoveBottom(*this); IdeRemoveRight(disas); } One PdbCreate(One host, const String& exefile, const String& cmdline) { Pdb *dbg = new Pdb; if(!dbg->Create(host, exefile, cmdline)) { delete dbg; return NULL; } return dbg; } #endif