Code::Blocks  SVN r11506
cdb_driver.cpp
Go to the documentation of this file.
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: 11339 $
6  * $Id: cdb_driver.cpp 11339 2018-03-20 08:39:38Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/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 // Parse CDB prompts. Support both 32 and 64 bit inferiors
31 // The strings looks something like this:
32 // 0:000>
33 // 0:000:x86>
34 static wxRegEx rePrompt(_T("([0-9]+:){1,2}[0-9]+(:x86)?>"));
35 
36 static wxRegEx reBP(_T("Breakpoint ([0-9]+) hit"));
37 // one stack frame (to access current file; is there another way???)
38 // # ChildEBP RetAddr
39 // 00 0012fe98 00401426 Win32GUI!WinMain+0x89 [c:\devel\tmp\win32 test\main.cpp @ 55]
40 static wxRegEx reFile(_T("[ \t]([A-z]+.*)[ \t]+\\[([A-z]:)(.*) @ ([0-9]+)\\]"));
41 
43  : DebuggerDriver(plugin),
44  m_Target(nullptr),
45  m_IsStarted(false)
46 {
47  //ctor
48 }
49 
51 {
52  //dtor
53 }
54 
56 {
57  wxString cmd;
58  cmd << debugger;
59 // cmd << _T(" -g"); // ignore starting breakpoint
60  cmd << _T(" -G"); // ignore ending breakpoint
61  cmd << _T(" -lines"); // line info
62 
64  cmd << wxT(" -2"); // tell the debugger to launch a console for us
65 
66  if (m_Dirs.GetCount() > 0)
67  {
68  // add symbols dirs
69  cmd << _T(" -y ");
70  for (unsigned int i = 0; i < m_Dirs.GetCount(); ++i)
71  cmd << m_Dirs[i] << wxPATH_SEP;
72 
73  // add source dirs
74  cmd << _T(" -srcpath ");
75  for (unsigned int i = 0; i < m_Dirs.GetCount(); ++i)
76  cmd << m_Dirs[i] << wxPATH_SEP;
77  }
78  return cmd;
79 }
80 
81 // FIXME (obfuscated#): Implement user arguments
82 wxString CDB_driver::GetCommandLine(const wxString& debugger, const wxString& debuggee, cb_unused const wxString &userArguments)
83 {
84  wxString cmd = GetCommonCommandLine(debugger);
85  cmd << _T(' ');
86 
87  // finally, add the program to debug
88  wxFileName debuggeeFileName(debuggee);
89  if (debuggeeFileName.IsAbsolute())
90  cmd << debuggee;
91  else
92  cmd << m_Target->GetParentProject()->GetBasePath() << wxT("/") << debuggee;
93 
94  return cmd;
95 }
96 
97 // FIXME (obfuscated#): Implement user arguments
98 wxString CDB_driver::GetCommandLine(const wxString& debugger, int pid, cb_unused const wxString &userArguments)
99 {
100  wxString cmd = GetCommonCommandLine(debugger);
101  // finally, add the PID
102  cmd << _T(" -p ") << wxString::Format(_T("%d"), pid);
103  return cmd;
104 }
106 {
107  m_Target = target;
108 }
109 
110 void CDB_driver::Prepare(cb_unused bool isConsole, cb_unused int printElements)
111 {
112  // The very first command won't get the right output back due to the spam on CDB launch.
113  // Throw in a dummy command to flush the output buffer.
114  m_QueueBusy = true;
115  QueueCommand(new DebuggerCmd(this,_T(".echo Clear buffer")),High);
116 
117  // Either way, get the PID of the child
118  QueueCommand(new CdbCmd_GetPID(this));
119 }
120 
121 void CDB_driver::Start(cb_unused bool breakOnEntry)
122 {
123  // start the process
124  QueueCommand(new DebuggerCmd(this, _T("l+t"))); // source mode
125  QueueCommand(new DebuggerCmd(this, _T("l+s"))); // show source lines
126  QueueCommand(new DebuggerCmd(this, _T("l+o"))); // only source lines
127 
129  {
130  QueueCommand(new CdbCmd_Continue(this));
131  m_IsStarted = true;
132  }
133 }
134 
136 {
137  ResetCursor();
138  QueueCommand(new DebuggerCmd(this, _T("q")));
139  m_IsStarted = false;
140 }
141 
143 {
144  ResetCursor();
145  QueueCommand(new CdbCmd_Continue(this));
146  m_IsStarted = true;
147 }
148 
150 {
151  ResetCursor();
152  QueueCommand(new DebuggerContinueBaseCmd(this, _T("p")));
153  // print a stack frame to find out about the file we 've stopped
154  QueueCommand(new CdbCmd_SwitchFrame(this, -1));
155 }
156 
158 {
159  NOT_IMPLEMENTED();
160 }
161 
163 {
164  NOT_IMPLEMENTED();
165 }
166 
168 {
169  ResetCursor();
170  QueueCommand(new DebuggerContinueBaseCmd(this, _T("t")));
171  Step();
172 }
173 
175 {
176  ResetCursor();
177  QueueCommand(new DebuggerContinueBaseCmd(this, _T("gu")));
178  QueueCommand(new CdbCmd_SwitchFrame(this, -1));
179 }
180 
181 void CDB_driver::SetNextStatement(cb_unused const wxString& filename, cb_unused int line)
182 {
183  NOT_IMPLEMENTED();
184 }
185 
187 {
188  DoBacktrace(false);
189 }
190 void CDB_driver::DoBacktrace(bool switchToFirst)
191 {
192  if (Manager::Get()->GetDebuggerManager()->UpdateBacktrace())
193  QueueCommand(new CdbCmd_Backtrace(this, switchToFirst));
194 }
195 
197 {
199 }
200 
202 {
204 }
205 
206 void CDB_driver::SwitchToFrame(size_t number)
207 {
208  ResetCursor();
209  QueueCommand(new CdbCmd_SwitchFrame(this, number));
210 }
211 
212 void CDB_driver::SetVarValue(cb_unused const wxString& var, cb_unused const wxString& value)
213 {
214  NOT_IMPLEMENTED();
215 }
216 
218 {
219  NOT_IMPLEMENTED();
220 }
221 
223 {
224  NOT_IMPLEMENTED();
225 }
226 
228 {
229  NOT_IMPLEMENTED();
230 }
231 
233 {
234  NOT_IMPLEMENTED();
235 }
236 
238 {
239  NOT_IMPLEMENTED();
240 }
241 
243 {
244  NOT_IMPLEMENTED();
245 }
246 
248 {
249  NOT_IMPLEMENTED();
250 }
251 
252 void CDB_driver::EnableCatchingThrow(cb_unused bool enable)
253 {
254  NOT_IMPLEMENTED();
255 }
256 
257 void CDB_driver::AddBreakpoint(cb::shared_ptr<DebuggerBreakpoint> bp)
258 {
259  QueueCommand(new CdbCmd_AddBreakpoint(this, bp));
260 }
261 
262 void CDB_driver::RemoveBreakpoint(cb::shared_ptr<DebuggerBreakpoint> bp)
263 {
264  QueueCommand(new CdbCmd_RemoveBreakpoint(this, bp));
265 }
266 
267 void CDB_driver::EvaluateSymbol(const wxString& symbol, const wxRect& tipRect)
268 {
269  QueueCommand(new CdbCmd_TooltipEvaluation(this, symbol, tipRect));
270 }
271 
272 void CDB_driver::UpdateWatches(cb_unused cb::shared_ptr<GDBWatch> localsWatch,
273  cb_unused cb::shared_ptr<GDBWatch> funcArgsWatch,
274  WatchesContainer &watches)
275 {
276  bool updateWatches = false;
277  for (WatchesContainer::iterator it = watches.begin(); it != watches.end(); ++it)
278  {
279  WatchesContainer::reference watch = *it;
280  if (watch->IsAutoUpdateEnabled())
281  {
282  QueueCommand(new CdbCmd_Watch(this, *it));
283  updateWatches = true;
284  }
285  }
286 
287  if (updateWatches)
289 
290  // FIXME (obfuscated#): reimplement this code
291 // // start updating watches tree
292 // tree->BeginUpdateTree();
293 //
294 // // locals before args because of precedence
295 // if (doLocals)
296 // QueueCommand(new CdbCmd_InfoLocals(this, tree));
299 // for (unsigned int i = 0; i < tree->GetWatches().GetCount(); ++i)
300 // {
301 // Watch& w = tree->GetWatches()[i];
302 // QueueCommand(new CdbCmd_Watch(this, tree, &w));
303 // }
304 //
305 // // run this action-only command to update the tree
306 // QueueCommand(new DbgCmd_UpdateWatchesTree(this, tree));
307 }
308 
309 void CDB_driver::UpdateWatch(const cb::shared_ptr<GDBWatch> &watch)
310 {
311  QueueCommand(new CdbCmd_Watch(this, watch));
313 }
314 
315 void CDB_driver::UpdateWatchLocalsArgs(cb_unused cb::shared_ptr<GDBWatch> const &watch,
316  cb_unused bool locals)
317 {
318  // FIXME (obfuscated#): implement this
319 }
320 
321 void CDB_driver::Attach(cb_unused int pid)
322 {
323  // FIXME (obfuscated#): implement this
324 }
325 
327 {
328  QueueCommand(new CdbCmd_Detach(this));
329 }
330 
332 {
333  m_Cursor.changed = false;
334  static wxString buffer;
335  buffer << output << _T('\n');
336 
337  m_pDBG->DebugLog(output);
338 
339  if (rePrompt.Matches(buffer))
340  {
341  int idx = buffer.First(rePrompt.GetMatch(buffer));
342  cbAssert(idx != wxNOT_FOUND);
343  m_ProgramIsStopped = true;
344  m_QueueBusy = false;
345  DebuggerCmd* cmd = CurrentCommand();
346  if (cmd)
347  {
348  RemoveTopCommand(false);
349  buffer.Remove(idx);
350  if (buffer[buffer.Length() - 1] == _T('\n'))
351  buffer.Remove(buffer.Length() - 1);
352  cmd->ParseOutput(buffer.Left(idx));
353  delete cmd;
354  RunQueue();
355  }
356  }
357  else
358  return; // come back later
359 
360  bool notifyChange = false;
361 
362  // non-command messages (e.g. breakpoint hits)
363  // break them up in lines
364  wxArrayString lines = GetArrayFromString(buffer, _T('\n'));
365  for (unsigned int i = 0; i < lines.GetCount(); ++i)
366  {
367 // Log(_T("DEBUG: ") + lines[i]); // write it in the full debugger log
368 
369  if (lines[i].StartsWith(_T("Cannot execute ")))
370  {
371  Log(lines[i]);
372  }
373  else if (lines[i].Contains(_T("Access violation")))
374  {
375  m_ProgramIsStopped = true;
376  Log(lines[i]);
378 
380  DoBacktrace(true);
381  InfoWindow::Display(_("Access violation"), lines[i]);
382  break;
383  }
384  else if (notifyChange)
385  continue;
386 
387  // Breakpoint 0 hit
388  // > 38: if (!RegisterClassEx (&wincl))
389  else if (reBP.Matches(lines[i]))
390  {
391  m_ProgramIsStopped = true;
392  Log(lines[i]);
393  // Code breakpoint / assert
396  DoBacktrace(true);
397  break;
398  }
399  else if (lines[i].Contains(_T("Break instruction exception")) && !m_pDBG->IsTemporaryBreak())
400  {
401  m_ProgramIsStopped = true;
402  // Code breakpoint / assert
405  DoBacktrace(true);
406  break;
407  }
408  }
409 
410  if (notifyChange)
412 
413  buffer.Clear();
414 }
415 
417 {
418  return m_IsStarted;
419 }
virtual void Backtrace()
Definition: cdb_driver.cpp:186
DLLIMPORT wxArrayString GetArrayFromString(const wxString &text, const wxString &separator=DEFAULT_ARRAY_SEP, bool trimSpaces=true)
Definition: globals.cpp:134
Command to remove a breakpoint.
Definition: cdb_commands.h:295
static void Display(const wxString &title, const wxString &message, unsigned int delay=5000, unsigned int hysteresis=1)
Definition: infowindow.cpp:294
virtual void StepOut()
Definition: cdb_driver.cpp:174
virtual void Attach(int pid)
Attach to process.
Definition: cdb_driver.cpp:321
virtual void Stop()
Stop debugging.
Definition: cdb_driver.cpp:135
void NotifyCursorChanged()
Called by implementations to notify cursor changes.
virtual void AddBreakpoint(cb::shared_ptr< DebuggerBreakpoint > bp)
Add a breakpoint.
Definition: cdb_driver.cpp:257
void InfoSignals()
Definition: cdb_driver.cpp:247
virtual void RunningThreads()
Definition: cdb_driver.cpp:222
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
virtual void SetNextStatement(const wxString &filename, int line)
Definition: cdb_driver.cpp:181
virtual void EvaluateSymbol(const wxString &symbol, const wxRect &tipRect)
Evaluate a symbol.
Definition: cdb_driver.cpp:267
Base class for all Continue type of commands.
virtual void CPURegisters()
Definition: cdb_driver.cpp:201
void RunQueue()
runs the next command in the queue, if it is idle
std::vector< cb::shared_ptr< GDBWatch > > WatchesContainer
DebuggerGDB * m_pDBG
Command to continue execution and notify the debugger plugin.
Definition: cdb_commands.h:227
void InfoFPU()
Definition: cdb_driver.cpp:242
static wxRegEx reFile(_T("[ \([A-z]+.*)[ \+\([A-z]:)(.*) @ ([0-9]+)\"))
void InfoFiles()
Definition: cdb_driver.cpp:237
virtual void ParseOutput(const wxString &output)
Parse debugger&#39;s output.
Definition: cdb_driver.cpp:331
virtual void SetTarget(ProjectBuildTarget *target)
Sets the target.
Definition: cdb_driver.cpp:105
void BringCBToFront()
Definition: cbplugin.cpp:913
void EnableCatchingThrow(bool enable)
Definition: cdb_driver.cpp:252
size_t Length() const
bool Matches(const wxString &text, int flags=0) const
#define _T(string)
Command to display a tooltip about a variables value.
Definition: cdb_commands.h:350
virtual void Start(bool breakOnEntry)
Begin the debugging process by launching a program.
Definition: cdb_driver.cpp:121
virtual ~CDB_driver()
Definition: cdb_driver.cpp:50
bool IsAbsolute(wxPathFormat format=wxPATH_NATIVE) const
wxString & Remove(size_t pos)
virtual void SwitchToFrame(size_t number)
Definition: cdb_driver.cpp:206
void RemoveTopCommand(bool deleteIt=true)
removes the top command (it has finished)
virtual void Detach()
Detach from running process.
Definition: cdb_driver.cpp:326
Action-only debugger command to signal the watches tree to update.
void Log(const wxString &msg)
#define wxT(string)
#define wxNOT_FOUND
Command to run a backtrace.
Definition: cdb_commands.h:400
virtual cbProject * GetParentProject()
void DoBacktrace(bool switchToFirst)
Definition: cdb_driver.cpp:190
virtual void StepInstruction()
Definition: cdb_driver.cpp:157
virtual void UpdateWatch(cb::shared_ptr< GDBWatch > const &watch)
Definition: cdb_driver.cpp:309
virtual TargetType GetTargetType() const
Read the target&#39;s type.
virtual void Disassemble()
Definition: cdb_driver.cpp:196
bool changed
Definition: debugger_defs.h:33
void InfoDLL()
Definition: cdb_driver.cpp:232
DebuggerManager * GetDebuggerManager() const
Definition: manager.cpp:484
Command to find the PID of the active child.
Definition: cdb_commands.h:135
null_pointer_t nullptr
Definition: nullptr.cpp:16
#define NOT_IMPLEMENTED()
virtual void SetVarValue(const wxString &var, const wxString &value)
Definition: cdb_driver.cpp:212
void ResetCursor()
Called by implementations to reset the cursor.
wxString Left(size_t count) const
virtual void StepIntoInstruction()
Definition: cdb_driver.cpp:162
virtual void UpdateWatches(cb::shared_ptr< GDBWatch > localsWatch, cb::shared_ptr< GDBWatch > funcArgsWatch, WatchesContainer &watches)
Update watches.
Definition: cdb_driver.cpp:272
wxString GetCommonCommandLine(const wxString &debugger)
Definition: cdb_driver.cpp:55
bool GetMatch(size_t *start, size_t *len, size_t index=0) const
virtual void UpdateWatchLocalsArgs(cb::shared_ptr< GDBWatch > const &watch, bool locals)
Definition: cdb_driver.cpp:315
virtual wxString GetBasePath() const
Read the target&#39;s base path, e.g. if GetFilename() returns "/usr/local/bin/xxx", base path will retur...
CDB_driver(DebuggerGDB *plugin)
Definition: cdb_driver.cpp:42
void QueueCommand(DebuggerCmd *dcmd, QueuePriority prio=Low)
add a command in the queue. The DebuggerCmd will be deleted automatically when finished.
wxArrayString m_Dirs
bool IsTemporaryBreak() const
Definition: debuggergdb.h:88
DebuggerConfiguration & GetActiveConfigEx()
Command to get info about a watched variable.
Definition: cdb_commands.h:321
Command to run a disassembly.
Definition: cdb_commands.h:594
const wxString & _(const wxString &string)
virtual void Step()
Definition: cdb_driver.cpp:149
#define cbAssert(expr)
Definition: cbexception.h:48
int First(wxUniChar ch) const
bool m_IsStarted
Definition: cdb_driver.h:71
virtual wxString GetCommandLine(const wxString &debugger, const wxString &debuggee, const wxString &userArguments)
Get the command-line to launch the debugger.
virtual void MemoryDump()
Definition: cdb_driver.cpp:217
void Clear()
void InfoFrame()
Definition: cdb_driver.cpp:227
Target produces a console executable (without GUI) (distinction between ttExecutable and ttConsoleOnl...
virtual void ParseOutput(const wxString &output)
Parses the command&#39;s output.
Command to add a breakpoint.
Definition: cdb_commands.h:244
virtual void StepIn()
Definition: cdb_driver.cpp:167
Represents a Code::Blocks project build target.
ProjectBuildTarget * m_Target
Definition: cdb_driver.h:70
static wxRegEx rePrompt(_T("([0-9]+:){1,2}[0-9]+(:x86)?>"))
size_t GetCount() const
DebuggerCmd * CurrentCommand()
returns the currently executing command
virtual void Continue()
Definition: cdb_driver.cpp:142
virtual void Prepare(bool isConsole, int printElements)
Prepares the debugging process by setting up search dirs etc.
Definition: cdb_driver.cpp:110
virtual bool IsDebuggingStarted() const
Is debugging started.
Definition: cdb_driver.cpp:416
Basic interface for debugger commands.
Definition: debugger_defs.h:49
static wxString Format(const wxString &format,...)
Command to run a disassembly.
Definition: cdb_commands.h:523
Command to the detach from the process.
Definition: cdb_commands.h:208
void DebugLog(const wxString &msg, Logger::level level=Logger::info)
Definition: cbplugin.cpp:540
virtual void RemoveBreakpoint(cb::shared_ptr< DebuggerBreakpoint > bp)
Remove a breakpoint.
Definition: cdb_driver.cpp:262
static wxRegEx reBP(_T("Breakpoint ([0-9]+) hit"))