~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/plugins/debuggergdb/cdb_driver.cpp

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
 
3
 * http://www.gnu.org/licenses/gpl-3.0.html
 
4
 *
 
5
 * $Revision: 10622 $
 
6
 * $Id: cdb_driver.cpp 10622 2015-12-11 19:56:36Z mortenmacfly $
 
7
 * $HeadURL: http://svn.code.sf.net/p/codeblocks/code/branches/release-16.xx/src/plugins/debuggergdb/cdb_driver.cpp $
 
8
 */
 
9
 
 
10
#include <sdk.h>
 
11
 
 
12
#ifndef CB_PRECOMP
 
13
    #include <cbproject.h>
 
14
    #include <cbexception.h>
 
15
    #include <configmanager.h>
 
16
    #include <debuggermanager.h>
 
17
    #include <globals.h>
 
18
    #include <infowindow.h>
 
19
    #include <logmanager.h>
 
20
    #include <manager.h>
 
21
    #include <projectbuildtarget.h>
 
22
#endif
 
23
 
 
24
#include "cdb_driver.h"
 
25
#include "cdb_commands.h"
 
26
#include "debuggeroptionsdlg.h"
 
27
 
 
28
#include <cbdebugger_interfaces.h>
 
29
 
 
30
static wxRegEx rePrompt(_T("([0-9]+:){1,2}[0-9]+>"));
 
31
static wxRegEx reBP(_T("Breakpoint ([0-9]+) hit"));
 
32
// one stack frame (to access current file; is there another way???)
 
33
//  # ChildEBP RetAddr
 
34
// 00 0012fe98 00401426 Win32GUI!WinMain+0x89 [c:\devel\tmp\win32 test\main.cpp @ 55]
 
35
static wxRegEx reFile(_T("[ \t]([A-z]+.*)[ \t]+\\[([A-z]:)(.*) @ ([0-9]+)\\]"));
 
36
 
 
37
CDB_driver::CDB_driver(DebuggerGDB* plugin)
 
38
    : DebuggerDriver(plugin),
 
39
    m_Target(nullptr),
 
40
    m_IsStarted(false)
 
41
{
 
42
    //ctor
 
43
}
 
44
 
 
45
CDB_driver::~CDB_driver()
 
46
{
 
47
    //dtor
 
48
}
 
49
 
 
50
wxString CDB_driver::GetCommonCommandLine(const wxString& debugger)
 
51
{
 
52
    wxString cmd;
 
53
    cmd << debugger;
 
54
//    cmd << _T(" -g"); // ignore starting breakpoint
 
55
    cmd << _T(" -G"); // ignore ending breakpoint
 
56
    cmd << _T(" -lines"); // line info
 
57
 
 
58
    if (m_Target->GetTargetType() == ttConsoleOnly)
 
59
        cmd << wxT(" -2"); // tell the debugger to launch a console for us
 
60
 
 
61
    if (m_Dirs.GetCount() > 0)
 
62
    {
 
63
        // add symbols dirs
 
64
        cmd << _T(" -y ");
 
65
        for (unsigned int i = 0; i < m_Dirs.GetCount(); ++i)
 
66
            cmd << m_Dirs[i] << wxPATH_SEP;
 
67
 
 
68
        // add source dirs
 
69
        cmd << _T(" -srcpath ");
 
70
        for (unsigned int i = 0; i < m_Dirs.GetCount(); ++i)
 
71
            cmd << m_Dirs[i] << wxPATH_SEP;
 
72
    }
 
73
    return cmd;
 
74
}
 
75
 
 
76
// FIXME (obfuscated#): Implement user arguments
 
77
wxString CDB_driver::GetCommandLine(const wxString& debugger, const wxString& debuggee, cb_unused const wxString &userArguments)
 
78
{
 
79
    wxString cmd = GetCommonCommandLine(debugger);
 
80
    cmd << _T(' ');
 
81
 
 
82
    // finally, add the program to debug
 
83
    wxFileName debuggeeFileName(debuggee);
 
84
    if (debuggeeFileName.IsAbsolute())
 
85
        cmd << debuggee;
 
86
    else
 
87
        cmd << m_Target->GetParentProject()->GetBasePath() << wxT("/") << debuggee;
 
88
 
 
89
    return cmd;
 
90
}
 
91
 
 
92
// FIXME (obfuscated#): Implement user arguments
 
93
wxString CDB_driver::GetCommandLine(const wxString& debugger, int pid, cb_unused const wxString &userArguments)
 
94
{
 
95
    wxString cmd = GetCommonCommandLine(debugger);
 
96
    // finally, add the PID
 
97
    cmd << _T(" -p ") << wxString::Format(_T("%d"), pid);
 
98
    return cmd;
 
99
}
 
100
void CDB_driver::SetTarget(ProjectBuildTarget* target)
 
101
{
 
102
    m_Target = target;
 
103
}
 
104
 
 
105
void CDB_driver::Prepare(cb_unused bool isConsole, cb_unused int printElements)
 
106
{
 
107
        // The very first command won't get the right output back due to the spam on CDB launch.
 
108
        // Throw in a dummy command to flush the output buffer.
 
109
        m_QueueBusy = true;
 
110
        QueueCommand(new DebuggerCmd(this,_T(".echo Clear buffer")),High);
 
111
 
 
112
        // Either way, get the PID of the child
 
113
        QueueCommand(new CdbCmd_GetPID(this));
 
114
}
 
115
 
 
116
void CDB_driver::Start(cb_unused bool breakOnEntry)
 
117
{
 
118
    // start the process
 
119
    QueueCommand(new DebuggerCmd(this, _T("l+t"))); // source mode
 
120
    QueueCommand(new DebuggerCmd(this, _T("l+s"))); // show source lines
 
121
    QueueCommand(new DebuggerCmd(this, _T("l+o"))); // only source lines
 
122
 
 
123
    if (!m_pDBG->GetActiveConfigEx().GetFlag(DebuggerConfiguration::DoNotRun))
 
124
    {
 
125
        QueueCommand(new CdbCmd_Continue(this));
 
126
        m_IsStarted = true;
 
127
    }
 
128
}
 
129
 
 
130
void CDB_driver::Stop()
 
131
{
 
132
    ResetCursor();
 
133
    QueueCommand(new DebuggerCmd(this, _T("q")));
 
134
    m_IsStarted = false;
 
135
}
 
136
 
 
137
void CDB_driver::Continue()
 
138
{
 
139
    ResetCursor();
 
140
    QueueCommand(new CdbCmd_Continue(this));
 
141
    m_IsStarted = true;
 
142
}
 
143
 
 
144
void CDB_driver::Step()
 
145
{
 
146
    ResetCursor();
 
147
    QueueCommand(new DebuggerContinueBaseCmd(this, _T("p")));
 
148
    // print a stack frame to find out about the file we 've stopped
 
149
    QueueCommand(new CdbCmd_SwitchFrame(this, -1));
 
150
}
 
151
 
 
152
void CDB_driver::StepInstruction()
 
153
{
 
154
    NOT_IMPLEMENTED();
 
155
}
 
156
 
 
157
void CDB_driver::StepIntoInstruction()
 
158
{
 
159
    NOT_IMPLEMENTED();
 
160
}
 
161
 
 
162
void CDB_driver::StepIn()
 
163
{
 
164
    ResetCursor();
 
165
    QueueCommand(new DebuggerContinueBaseCmd(this, _T("t")));
 
166
    Step();
 
167
}
 
168
 
 
169
void CDB_driver::StepOut()
 
170
{
 
171
    ResetCursor();
 
172
    QueueCommand(new DebuggerContinueBaseCmd(this, _T("gu")));
 
173
    QueueCommand(new CdbCmd_SwitchFrame(this, -1));
 
174
}
 
175
 
 
176
void CDB_driver::SetNextStatement(cb_unused const wxString& filename, cb_unused int line)
 
177
{
 
178
    NOT_IMPLEMENTED();
 
179
}
 
180
 
 
181
void CDB_driver::Backtrace()
 
182
{
 
183
    DoBacktrace(false);
 
184
}
 
185
void CDB_driver::DoBacktrace(bool switchToFirst)
 
186
{
 
187
    if (Manager::Get()->GetDebuggerManager()->UpdateBacktrace())
 
188
        QueueCommand(new CdbCmd_Backtrace(this, switchToFirst));
 
189
}
 
190
 
 
191
void CDB_driver::Disassemble()
 
192
{
 
193
    QueueCommand(new CdbCmd_DisassemblyInit(this));
 
194
}
 
195
 
 
196
void CDB_driver::CPURegisters()
 
197
{
 
198
    QueueCommand(new CdbCmd_InfoRegisters(this));
 
199
}
 
200
 
 
201
void CDB_driver::SwitchToFrame(size_t number)
 
202
{
 
203
    ResetCursor();
 
204
    QueueCommand(new CdbCmd_SwitchFrame(this, number));
 
205
}
 
206
 
 
207
void CDB_driver::SetVarValue(cb_unused const wxString& var, cb_unused const wxString& value)
 
208
{
 
209
    NOT_IMPLEMENTED();
 
210
}
 
211
 
 
212
void CDB_driver::MemoryDump()
 
213
{
 
214
    NOT_IMPLEMENTED();
 
215
}
 
216
 
 
217
void CDB_driver::RunningThreads()
 
218
{
 
219
    NOT_IMPLEMENTED();
 
220
}
 
221
 
 
222
void CDB_driver::InfoFrame()
 
223
{
 
224
    NOT_IMPLEMENTED();
 
225
}
 
226
 
 
227
void CDB_driver::InfoDLL()
 
228
{
 
229
    NOT_IMPLEMENTED();
 
230
}
 
231
 
 
232
void CDB_driver::InfoFiles()
 
233
{
 
234
    NOT_IMPLEMENTED();
 
235
}
 
236
 
 
237
void CDB_driver::InfoFPU()
 
238
{
 
239
    NOT_IMPLEMENTED();
 
240
}
 
241
 
 
242
void CDB_driver::InfoSignals()
 
243
{
 
244
    NOT_IMPLEMENTED();
 
245
}
 
246
 
 
247
void CDB_driver::EnableCatchingThrow(cb_unused bool enable)
 
248
{
 
249
    NOT_IMPLEMENTED();
 
250
}
 
251
 
 
252
void CDB_driver::AddBreakpoint(cb::shared_ptr<DebuggerBreakpoint> bp)
 
253
{
 
254
    QueueCommand(new CdbCmd_AddBreakpoint(this, bp));
 
255
}
 
256
 
 
257
void CDB_driver::RemoveBreakpoint(cb::shared_ptr<DebuggerBreakpoint> bp)
 
258
{
 
259
    QueueCommand(new CdbCmd_RemoveBreakpoint(this, bp));
 
260
}
 
261
 
 
262
void CDB_driver::EvaluateSymbol(const wxString& symbol, const wxRect& tipRect)
 
263
{
 
264
    QueueCommand(new CdbCmd_TooltipEvaluation(this, symbol, tipRect));
 
265
}
 
266
 
 
267
void CDB_driver::UpdateWatches(cb_unused cb::shared_ptr<GDBWatch> localsWatch,
 
268
                               cb_unused cb::shared_ptr<GDBWatch> funcArgsWatch,
 
269
                               WatchesContainer &watches)
 
270
{
 
271
    bool updateWatches = false;
 
272
    for (WatchesContainer::iterator it = watches.begin(); it != watches.end(); ++it)
 
273
    {
 
274
        WatchesContainer::reference watch = *it;
 
275
        if (watch->IsAutoUpdateEnabled())
 
276
        {
 
277
            QueueCommand(new CdbCmd_Watch(this, *it));
 
278
            updateWatches = true;
 
279
        }
 
280
    }
 
281
 
 
282
    if (updateWatches)
 
283
        QueueCommand(new DbgCmd_UpdateWatchesTree(this));
 
284
 
 
285
    // FIXME (obfuscated#): reimplement this code
 
286
//    // start updating watches tree
 
287
//    tree->BeginUpdateTree();
 
288
//
 
289
//    // locals before args because of precedence
 
290
//    if (doLocals)
 
291
//        QueueCommand(new CdbCmd_InfoLocals(this, tree));
 
292
////    if (doArgs)
 
293
////        QueueCommand(new CdbCmd_InfoArguments(this, tree));
 
294
//    for (unsigned int i = 0; i < tree->GetWatches().GetCount(); ++i)
 
295
//    {
 
296
//        Watch& w = tree->GetWatches()[i];
 
297
//        QueueCommand(new CdbCmd_Watch(this, tree, &w));
 
298
//    }
 
299
//
 
300
//    // run this action-only command to update the tree
 
301
//    QueueCommand(new DbgCmd_UpdateWatchesTree(this, tree));
 
302
}
 
303
 
 
304
void CDB_driver::UpdateWatch(const cb::shared_ptr<GDBWatch> &watch)
 
305
{
 
306
    QueueCommand(new CdbCmd_Watch(this, watch));
 
307
    QueueCommand(new DbgCmd_UpdateWatchesTree(this));
 
308
}
 
309
 
 
310
void CDB_driver::UpdateWatchLocalsArgs(cb::shared_ptr<GDBWatch> const &watch, bool locals)
 
311
{
 
312
    // FIXME (obfuscated#): implement this
 
313
}
 
314
 
 
315
void CDB_driver::Attach(cb_unused int pid)
 
316
{
 
317
    // FIXME (obfuscated#): implement this
 
318
}
 
319
 
 
320
void CDB_driver::Detach()
 
321
{
 
322
    QueueCommand(new CdbCmd_Detach(this));
 
323
}
 
324
 
 
325
void CDB_driver::ParseOutput(const wxString& output)
 
326
{
 
327
    m_Cursor.changed = false;
 
328
    static wxString buffer;
 
329
    buffer << output << _T('\n');
 
330
 
 
331
    m_pDBG->DebugLog(output);
 
332
 
 
333
    if (rePrompt.Matches(buffer))
 
334
    {
 
335
        int idx = buffer.First(rePrompt.GetMatch(buffer));
 
336
        cbAssert(idx != wxNOT_FOUND);
 
337
        m_ProgramIsStopped = true;
 
338
        m_QueueBusy = false;
 
339
        DebuggerCmd* cmd = CurrentCommand();
 
340
        if (cmd)
 
341
        {
 
342
            RemoveTopCommand(false);
 
343
            buffer.Remove(idx);
 
344
            if (buffer[buffer.Length() - 1] == _T('\n'))
 
345
                buffer.Remove(buffer.Length() - 1);
 
346
            cmd->ParseOutput(buffer.Left(idx));
 
347
            delete cmd;
 
348
            RunQueue();
 
349
        }
 
350
    }
 
351
    else
 
352
        return; // come back later
 
353
 
 
354
    bool notifyChange = false;
 
355
 
 
356
    // non-command messages (e.g. breakpoint hits)
 
357
    // break them up in lines
 
358
    wxArrayString lines = GetArrayFromString(buffer, _T('\n'));
 
359
    for (unsigned int i = 0; i < lines.GetCount(); ++i)
 
360
    {
 
361
//            Log(_T("DEBUG: ") + lines[i]); // write it in the full debugger log
 
362
 
 
363
        if (lines[i].StartsWith(_T("Cannot execute ")))
 
364
        {
 
365
            Log(lines[i]);
 
366
        }
 
367
        else if (lines[i].Contains(_T("Access violation")))
 
368
        {
 
369
            m_ProgramIsStopped = true;
 
370
            Log(lines[i]);
 
371
            m_pDBG->BringCBToFront();
 
372
 
 
373
            Manager::Get()->GetDebuggerManager()->ShowBacktraceDialog();
 
374
            DoBacktrace(true);
 
375
            InfoWindow::Display(_("Access violation"), lines[i]);
 
376
            break;
 
377
        }
 
378
        else if (notifyChange)
 
379
            continue;
 
380
 
 
381
        // Breakpoint 0 hit
 
382
        // >   38:     if (!RegisterClassEx (&wincl))
 
383
        else if (reBP.Matches(lines[i]))
 
384
        {
 
385
            m_ProgramIsStopped = true;
 
386
            Log(lines[i]);
 
387
            // Code breakpoint / assert
 
388
            m_pDBG->BringCBToFront();
 
389
            Manager::Get()->GetDebuggerManager()->ShowBacktraceDialog();
 
390
            DoBacktrace(true);
 
391
            break;
 
392
        }
 
393
        else if (lines[i].Contains(_T("Break instruction exception")) && !m_pDBG->IsTemporaryBreak())
 
394
        {
 
395
            m_ProgramIsStopped = true;
 
396
                // Code breakpoint / assert
 
397
            m_pDBG->BringCBToFront();
 
398
            Manager::Get()->GetDebuggerManager()->ShowBacktraceDialog();
 
399
            DoBacktrace(true);
 
400
            break;
 
401
        }
 
402
    }
 
403
 
 
404
    if (notifyChange)
 
405
        NotifyCursorChanged();
 
406
 
 
407
    buffer.Clear();
 
408
}
 
409
 
 
410
bool CDB_driver::IsDebuggingStarted() const
 
411
{
 
412
    return m_IsStarted;
 
413
}