Pdb.cpp

Pdb toolbar update - Zbigniew Rebacz, 11/19/2013 01:01 PM

Download (8.35 KB)

 
1
#include "Debuggers.h"
2

    
3
#ifdef COMPILER_MSC
4

    
5
#pragma comment(lib, "DbgHelp.lib")
6
#pragma comment(lib, "psapi.lib")
7

    
8
#define LLOG(x) // LOG(x)
9

    
10
#define KEYGROUPNAME "PdbDebugger"
11
#define KEYNAMESPACE PdbKeys
12
#define KEYFILE      <ide/Debuggers/Pdb.key>
13
#include             <CtrlLib/key_source.h>
14

    
15
using namespace PdbKeys;
16

    
17
void Pdb::DebugBar(Bar& bar)
18
{
19
        bar.Add(AK_STOP, DbgImg::StopDebug(), THISBACK(Stop));
20
        bool b = !IdeIsDebugLock();
21
        bar.Separator();
22
        bar.Add(b, AK_STEPINTO, DbgImg::StepInto(), THISBACK1(Trace, false));
23
        bar.Add(b, AK_STEPOVER, DbgImg::StepOver(), THISBACK1(Trace, true));
24
        bar.Add(b, AK_STEPOUT, DbgImg::StepOut(), THISBACK(StepOut));
25
        bar.Add(b, AK_RUNTO, DbgImg::RunTo(), THISBACK(DoRunTo));
26
        bar.Add(b, AK_RUN, DbgImg::Run(), THISBACK(Run));
27
        bar.Add(b, AK_SETIP, DbgImg::SetIp(), THISBACK(SetIp));
28
        bar.Add(!b, AK_STOP, DbgImg::Stop(), THISBACK(BreakRunning));
29
        bar.MenuSeparator();
30
        bar.Add(b, AK_AUTOS, THISBACK1(SetTab, 0));
31
        bar.Add(b, AK_LOCALS, THISBACK1(SetTab, 1));
32
        bar.Add(b, AK_WATCHES, THISBACK1(SetTab, 2));
33
        bar.Add(b, AK_CLEARWATCHES, THISBACK(ClearWatches));
34
        bar.Add(b, AK_ADDWATCH, THISBACK(AddWatch));
35
        bar.Add(b, AK_EXPLORER, THISBACK(DoExplorer));
36
        bar.Add(b, AK_MEMORY, THISBACK1(SetTab, 4));
37
        bar.MenuSeparator();
38
        bar.Add(b, "Copy backtrace", THISBACK(CopyStack));
39
        bar.Add(b, "Copy dissassembly", THISBACK(CopyDisas));
40
}
41

    
42
void Pdb::Tab()
43
{
44
        switch(tab.Get()) {
45
        case 0: autos.SetFocus(); break;
46
        case 1: locals.SetFocus(); break;
47
        case 2: watches.SetFocus(); break;
48
        case 3: explorer.SetFocus(); break;
49
        case 4: memory.SetFocus(); break;
50
        }
51
        Data();
52
}
53

    
54
bool Pdb::Key(dword key, int count)
55
{
56
        if(key >= 32 && key < 65535 && tab.Get() == 2) {
57
                watches.DoInsertAfter();
58
                Ctrl* f = GetFocusCtrl();
59
                if(f && watches.HasChildDeep(f))
60
                        f->Key(key, count);
61
                return true;
62
        }
63
        if(key == K_ENTER && expexp.HasFocus()) {
64
                Explore(~expexp);
65
                return true;
66
        }
67
        return Ctrl::Key(key, count);
68
}
69

    
70
#define CONFIGNAME "pdb debugger"
71

    
72
void Pdb::Serialize(Stream& s)
73
{
74
        int version = 0;
75
        s / version;
76
        memory.SerializeSettings(s);
77
        s % split;
78
}
79

    
80
INITBLOCK
81
{
82
        RegisterGlobalConfig(CONFIGNAME);
83
}
84

    
85
bool Pdb::Create(One<Host> local, const String& exefile, const String& cmdline)
86
{
87
        STARTUPINFO si;
88
        ZeroMemory(&si, sizeof(STARTUPINFO));
89
        si.cb = sizeof(STARTUPINFO);
90
        si.dwFlags = 0;
91
        String cl;
92
        if(exefile.Find(' ') >= 0)
93
                cl << '\"' << exefile << '\"';
94
        else
95
                cl << exefile;
96
        if(!IsNull(cmdline))
97
                cl << ' ' << cmdline;
98

    
99
        Buffer<char> cmd(cl.GetLength() + 1);
100
        memcpy(cmd, cl, cl.GetLength() + 1);
101
        PROCESS_INFORMATION pi;
102
        ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
103
        Buffer<char> env(local->GetEnvironment().GetCount() + 1);
104
        memcpy(env, ~local->GetEnvironment(), local->GetEnvironment().GetCount() + 1);
105
        bool h = CreateProcess(exefile, cmd, NULL, NULL, TRUE,
106
                               NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE|DEBUG_ONLY_THIS_PROCESS|DEBUG_PROCESS,
107
                               ~env, NULL, &si, &pi);
108
        if(!h) {
109
                Exclamation("Error creating process&[* " + DeQtf(exefile) + "]&" +
110
                            "Windows error: " + DeQtf(GetLastErrorMessage()));
111
                return false;
112
        }
113
        hProcess = pi.hProcess;
114
        CloseHandle(pi.hThread);
115

    
116
        IdeSetBottom(*this);
117
        IdeSetRight(disas);
118

    
119
        LoadFromGlobal(*this, CONFIGNAME);
120

    
121
        if(!SymInitialize(hProcess, 0, FALSE)) {
122
                Error();
123
                return false;
124
        }
125
        SymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_UNDNAME|SYMOPT_NO_UNQUALIFIED_LOADS);
126

    
127
        lock = 0;
128
        stop = false;
129
        refreshmodules = true;
130
        terminated = false;
131

    
132
        running = true;
133

    
134
        RunToException();
135
//        Sync();
136

    
137
        return true;
138
}
139

    
140
INITBLOCK {
141
        RegisterWorkspaceConfig("pdb-debugger");
142
}
143

    
144
void Pdb::SerializeSession(Stream& s)
145
{
146
        int version = 0;
147
        s / version;
148
        int n = watches.GetCount();
149
        s / n;
150
        for(int i = 0; i < n; i++) {
151
                String w;
152
                if(s.IsStoring())
153
                        w = watches.Get(i, 0);
154
                s % w;
155
                if(s.IsLoading())
156
                        watches.Add(w);
157
        }
158
}
159

    
160
Pdb::Pdb()
161
{
162
        hProcess = INVALID_HANDLE_VALUE;
163

    
164
        CtrlLayout(regs);
165
        regs.Height(regs.GetLayoutSize().cy);
166
        AddReg("eax", &regs.eax);
167
        AddReg("ebx", &regs.ebx);
168
        AddReg("ecx", &regs.ecx);
169
        AddReg("edx", &regs.edx);
170
        AddReg("esi", &regs.esi);
171
        AddReg("edi", &regs.edi);
172
        AddReg("ebp", &regs.ebp);
173
        AddReg("esp", &regs.esp);
174
        regs.Color(SColorLtFace);
175
        regs.AddFrame(TopSeparatorFrame());
176
        regs.AddFrame(RightSeparatorFrame());
177

    
178
        locals.NoHeader();
179
        locals.AddColumn("", 1);
180
        locals.AddColumn("", 6).SetDisplay(Single<VisualDisplay>());
181
        locals.WhenEnterRow = THISBACK1(SetTreeA, &locals);
182
        locals.WhenBar = THISBACK(LocalsMenu);
183
        locals.WhenLeftDouble = THISBACK1(ExploreKey, &locals);
184

    
185
        watches.NoHeader();
186
        watches.AddColumn("", 1).Edit(watchedit);
187
        watches.AddColumn("", 6).SetDisplay(Single<VisualDisplay>());
188
        watches.Inserting().Removing();
189
        watches.WhenEnterRow = THISBACK1(SetTreeA, &watches);
190
        watches.WhenBar = THISBACK(WatchesMenu);
191
        watches.WhenLeftDouble = THISBACK1(ExploreKey, &watches);
192

    
193
        autos.NoHeader();
194
        autos.AddColumn("", 1);
195
        autos.AddColumn("", 6).SetDisplay(Single<VisualDisplay>());
196
        autos.WhenEnterRow = THISBACK1(SetTreeA, &autos);
197
        autos.WhenBar = THISBACK(AutosMenu);
198
        autos.WhenLeftDouble = THISBACK1(ExploreKey, &autos);
199

    
200
        int c = EditField::GetStdHeight();
201
        explorer.AddColumn("", 1);
202
        explorer.AddColumn("", 6).SetDisplay(Single<VisualDisplay>());
203
        explorer_pane.Add(exback.LeftPos(0, c).TopPos(0, c));
204
        explorer_pane.Add(exfw.LeftPos(c + 2, c).TopPos(0, c));
205
        explorer_pane.Add(expexp.HSizePos(2 * c + 4).TopPos(0, c));
206
        explorer_pane.Add(explorer.HSizePos().VSizePos(EditField::GetStdHeight(), 0));
207
        explorer.NoHeader();
208
        explorer.WhenEnterRow = THISBACK(ExplorerTree);
209
        explorer.WhenLeftDouble = THISBACK(ExpExp);
210
        explorer.WhenBar = THISBACK(ExplorerMenu);
211

    
212
        exback.SetImage(DbgImg::ExplorerBack());
213
        exback <<= THISBACK(ExBack);
214
        exfw.SetImage(DbgImg::ExplorerFw());
215
        exfw <<= THISBACK(ExFw);
216
        exback.Disable();
217
        exfw.Disable();
218

    
219
        tab.Add(autos.SizePos(), "Autos");
220
        tab.Add(locals.SizePos(), "Locals");
221
        tab.Add(watches.SizePos(), "Watches");
222
        tab.Add(explorer_pane.SizePos(), "Explorer");
223
        memory.cdb = this;
224
        tab.Add(memory.SizePos(), "Memory");
225

    
226
        dlock = "  Running..";
227
        dlock.SetFrame(BlackFrame());
228
        dlock.SetInk(Red);
229
        dlock.NoTransparent();
230
        dlock.Hide();
231
        framelist.Ctrl::Add(dlock.SizePos());
232

    
233
        pane.Add(tab.SizePos());
234
        pane.Add(threadlist.LeftPosZ(320, 60).TopPos(2, EditField::GetStdHeight()));
235
        pane.Add(framelist.HSizePosZ(384, 0).TopPos(2, EditField::GetStdHeight()));
236
        split.Horz(pane, tree.SizePos());
237
        split.SetPos(8000);
238
        Add(split);
239

    
240
        disas.AddFrame(regs);
241
        disas.WhenCursor = THISBACK(DisasCursor);
242
        disas.WhenFocus = THISBACK(DisasFocus);
243

    
244
        memory.WhenGoto = THISBACK(MemoryGoto);
245

    
246
        tab <<= THISBACK(Tab);
247

    
248
        framelist <<= THISBACK(SetFrame);
249
        threadlist <<= THISBACK(SetThread);
250

    
251
        watches.WhenAcceptEdit = THISBACK(Data);
252
        watches.WhenDrop = THISBACK(DropWatch);
253
        tab <<= THISBACK(Data);
254

    
255
        tree.WhenOpen = THISBACK(TreeExpand);
256

    
257
        FileIn in(ConfigFile("TreeTypes.txt"));
258
        while(!in.IsEof()) {
259
                String type = in.GetLine();
260
                String desc = in.GetLine();
261
                treetype.Add(type, desc);
262
        }
263
        StringStream ss(WorkspaceConfigData("pdb-debugger"));
264
        Load(callback(this, &Pdb::SerializeSession), ss);
265
}
266

    
267
void Pdb::CleanupOnExit()
268
{
269
        if(hProcess != INVALID_HANDLE_VALUE) {
270
                while(threads.GetCount())
271
                        RemoveThread(threads.GetKey(0));
272
                UnloadModuleSymbols();
273
                SymCleanup(hProcess);
274
                CloseHandle(hProcess);
275
                hProcess = INVALID_HANDLE_VALUE;
276
        }
277
}
278

    
279
void Pdb::CopyStack()
280
{
281
        String s;
282
        for(int i = 0; i < framelist.GetCount(); i++)
283
                s << framelist.GetValue(i) << "\n";
284
        WriteClipboardText(s);
285
}
286

    
287
void Pdb::CopyDisas()
288
{
289
        disas.WriteClipboard();
290
}
291

    
292
Pdb::~Pdb()
293
{
294
        SaveTree();
295
        String fn = ConfigFile("TreeTypes.txt");
296
        FileOut out(fn);
297
        for(int i = 0; i < treetype.GetCount(); i++)
298
                out << treetype.GetKey(i) << "\r\n" << treetype[i] << "\r\n";
299
        StringStream ss;
300
        Store(callback(this, &Pdb::SerializeSession), ss);
301
        WorkspaceConfigData("pdb-debugger") = ss;
302
        if(hProcess != INVALID_HANDLE_VALUE) {
303
                if(!running)
304
                        ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
305
                TerminateProcess(hProcess, -1);
306
                do {
307
                        if(!WaitForDebugEvent(&event, INFINITE))
308
                                break;
309
                        if(!ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE))
310
                                break;
311
                }
312
                while(event.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
313
                CleanupOnExit();
314
        }
315
        StoreToGlobal(*this, CONFIGNAME);
316
        IdeRemoveBottom(*this);
317
        IdeRemoveRight(disas);
318
}
319

    
320
One<Debugger> PdbCreate(One<Host> host, const String& exefile, const String& cmdline)
321
{
322
        One<Debugger> dbg;
323
        if(!dbg.Create<Pdb>().Create(host, exefile, cmdline))
324
                dbg.Clear();
325
        return dbg;
326
}
327

    
328
#endif