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
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 $
13
#include <cbproject.h>
14
#include <cbexception.h>
15
#include <configmanager.h>
16
#include <debuggermanager.h>
18
#include <infowindow.h>
19
#include <logmanager.h>
21
#include <projectbuildtarget.h>
24
#include "cdb_driver.h"
25
#include "cdb_commands.h"
26
#include "debuggeroptionsdlg.h"
28
#include <cbdebugger_interfaces.h>
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???)
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]+)\\]"));
37
CDB_driver::CDB_driver(DebuggerGDB* plugin)
38
: DebuggerDriver(plugin),
45
CDB_driver::~CDB_driver()
50
wxString CDB_driver::GetCommonCommandLine(const wxString& debugger)
54
// cmd << _T(" -g"); // ignore starting breakpoint
55
cmd << _T(" -G"); // ignore ending breakpoint
56
cmd << _T(" -lines"); // line info
58
if (m_Target->GetTargetType() == ttConsoleOnly)
59
cmd << wxT(" -2"); // tell the debugger to launch a console for us
61
if (m_Dirs.GetCount() > 0)
65
for (unsigned int i = 0; i < m_Dirs.GetCount(); ++i)
66
cmd << m_Dirs[i] << wxPATH_SEP;
69
cmd << _T(" -srcpath ");
70
for (unsigned int i = 0; i < m_Dirs.GetCount(); ++i)
71
cmd << m_Dirs[i] << wxPATH_SEP;
76
// FIXME (obfuscated#): Implement user arguments
77
wxString CDB_driver::GetCommandLine(const wxString& debugger, const wxString& debuggee, cb_unused const wxString &userArguments)
79
wxString cmd = GetCommonCommandLine(debugger);
82
// finally, add the program to debug
83
wxFileName debuggeeFileName(debuggee);
84
if (debuggeeFileName.IsAbsolute())
87
cmd << m_Target->GetParentProject()->GetBasePath() << wxT("/") << debuggee;
92
// FIXME (obfuscated#): Implement user arguments
93
wxString CDB_driver::GetCommandLine(const wxString& debugger, int pid, cb_unused const wxString &userArguments)
95
wxString cmd = GetCommonCommandLine(debugger);
96
// finally, add the PID
97
cmd << _T(" -p ") << wxString::Format(_T("%d"), pid);
100
void CDB_driver::SetTarget(ProjectBuildTarget* target)
105
void CDB_driver::Prepare(cb_unused bool isConsole, cb_unused int printElements)
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.
110
QueueCommand(new DebuggerCmd(this,_T(".echo Clear buffer")),High);
112
// Either way, get the PID of the child
113
QueueCommand(new CdbCmd_GetPID(this));
116
void CDB_driver::Start(cb_unused bool breakOnEntry)
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
123
if (!m_pDBG->GetActiveConfigEx().GetFlag(DebuggerConfiguration::DoNotRun))
125
QueueCommand(new CdbCmd_Continue(this));
130
void CDB_driver::Stop()
133
QueueCommand(new DebuggerCmd(this, _T("q")));
137
void CDB_driver::Continue()
140
QueueCommand(new CdbCmd_Continue(this));
144
void CDB_driver::Step()
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));
152
void CDB_driver::StepInstruction()
157
void CDB_driver::StepIntoInstruction()
162
void CDB_driver::StepIn()
165
QueueCommand(new DebuggerContinueBaseCmd(this, _T("t")));
169
void CDB_driver::StepOut()
172
QueueCommand(new DebuggerContinueBaseCmd(this, _T("gu")));
173
QueueCommand(new CdbCmd_SwitchFrame(this, -1));
176
void CDB_driver::SetNextStatement(cb_unused const wxString& filename, cb_unused int line)
181
void CDB_driver::Backtrace()
185
void CDB_driver::DoBacktrace(bool switchToFirst)
187
if (Manager::Get()->GetDebuggerManager()->UpdateBacktrace())
188
QueueCommand(new CdbCmd_Backtrace(this, switchToFirst));
191
void CDB_driver::Disassemble()
193
QueueCommand(new CdbCmd_DisassemblyInit(this));
196
void CDB_driver::CPURegisters()
198
QueueCommand(new CdbCmd_InfoRegisters(this));
201
void CDB_driver::SwitchToFrame(size_t number)
204
QueueCommand(new CdbCmd_SwitchFrame(this, number));
207
void CDB_driver::SetVarValue(cb_unused const wxString& var, cb_unused const wxString& value)
212
void CDB_driver::MemoryDump()
217
void CDB_driver::RunningThreads()
222
void CDB_driver::InfoFrame()
227
void CDB_driver::InfoDLL()
232
void CDB_driver::InfoFiles()
237
void CDB_driver::InfoFPU()
242
void CDB_driver::InfoSignals()
247
void CDB_driver::EnableCatchingThrow(cb_unused bool enable)
252
void CDB_driver::AddBreakpoint(cb::shared_ptr<DebuggerBreakpoint> bp)
254
QueueCommand(new CdbCmd_AddBreakpoint(this, bp));
257
void CDB_driver::RemoveBreakpoint(cb::shared_ptr<DebuggerBreakpoint> bp)
259
QueueCommand(new CdbCmd_RemoveBreakpoint(this, bp));
262
void CDB_driver::EvaluateSymbol(const wxString& symbol, const wxRect& tipRect)
264
QueueCommand(new CdbCmd_TooltipEvaluation(this, symbol, tipRect));
267
void CDB_driver::UpdateWatches(cb_unused cb::shared_ptr<GDBWatch> localsWatch,
268
cb_unused cb::shared_ptr<GDBWatch> funcArgsWatch,
269
WatchesContainer &watches)
271
bool updateWatches = false;
272
for (WatchesContainer::iterator it = watches.begin(); it != watches.end(); ++it)
274
WatchesContainer::reference watch = *it;
275
if (watch->IsAutoUpdateEnabled())
277
QueueCommand(new CdbCmd_Watch(this, *it));
278
updateWatches = true;
283
QueueCommand(new DbgCmd_UpdateWatchesTree(this));
285
// FIXME (obfuscated#): reimplement this code
286
// // start updating watches tree
287
// tree->BeginUpdateTree();
289
// // locals before args because of precedence
291
// QueueCommand(new CdbCmd_InfoLocals(this, tree));
293
//// QueueCommand(new CdbCmd_InfoArguments(this, tree));
294
// for (unsigned int i = 0; i < tree->GetWatches().GetCount(); ++i)
296
// Watch& w = tree->GetWatches()[i];
297
// QueueCommand(new CdbCmd_Watch(this, tree, &w));
300
// // run this action-only command to update the tree
301
// QueueCommand(new DbgCmd_UpdateWatchesTree(this, tree));
304
void CDB_driver::UpdateWatch(const cb::shared_ptr<GDBWatch> &watch)
306
QueueCommand(new CdbCmd_Watch(this, watch));
307
QueueCommand(new DbgCmd_UpdateWatchesTree(this));
310
void CDB_driver::UpdateWatchLocalsArgs(cb::shared_ptr<GDBWatch> const &watch, bool locals)
312
// FIXME (obfuscated#): implement this
315
void CDB_driver::Attach(cb_unused int pid)
317
// FIXME (obfuscated#): implement this
320
void CDB_driver::Detach()
322
QueueCommand(new CdbCmd_Detach(this));
325
void CDB_driver::ParseOutput(const wxString& output)
327
m_Cursor.changed = false;
328
static wxString buffer;
329
buffer << output << _T('\n');
331
m_pDBG->DebugLog(output);
333
if (rePrompt.Matches(buffer))
335
int idx = buffer.First(rePrompt.GetMatch(buffer));
336
cbAssert(idx != wxNOT_FOUND);
337
m_ProgramIsStopped = true;
339
DebuggerCmd* cmd = CurrentCommand();
342
RemoveTopCommand(false);
344
if (buffer[buffer.Length() - 1] == _T('\n'))
345
buffer.Remove(buffer.Length() - 1);
346
cmd->ParseOutput(buffer.Left(idx));
352
return; // come back later
354
bool notifyChange = false;
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)
361
// Log(_T("DEBUG: ") + lines[i]); // write it in the full debugger log
363
if (lines[i].StartsWith(_T("Cannot execute ")))
367
else if (lines[i].Contains(_T("Access violation")))
369
m_ProgramIsStopped = true;
371
m_pDBG->BringCBToFront();
373
Manager::Get()->GetDebuggerManager()->ShowBacktraceDialog();
375
InfoWindow::Display(_("Access violation"), lines[i]);
378
else if (notifyChange)
382
// > 38: if (!RegisterClassEx (&wincl))
383
else if (reBP.Matches(lines[i]))
385
m_ProgramIsStopped = true;
387
// Code breakpoint / assert
388
m_pDBG->BringCBToFront();
389
Manager::Get()->GetDebuggerManager()->ShowBacktraceDialog();
393
else if (lines[i].Contains(_T("Break instruction exception")) && !m_pDBG->IsTemporaryBreak())
395
m_ProgramIsStopped = true;
396
// Code breakpoint / assert
397
m_pDBG->BringCBToFront();
398
Manager::Get()->GetDebuggerManager()->ShowBacktraceDialog();
405
NotifyCursorChanged();
410
bool CDB_driver::IsDebuggingStarted() const