1 /*
2  * Copyright Johannes Sixt
3  * This file is licensed under the GNU General Public License Version 2.
4  * See the file COPYING in the toplevel directory of the source directory.
5  */
6 
7 #include "debugger.h"
8 #include "dbgdriver.h"
9 #include "pgmargs.h"
10 #include "typetable.h"
11 #include "exprwnd.h"
12 #include "pgmsettings.h"
13 #include <QFileInfo>
14 #include <QListWidget>
15 #include <QApplication>
16 #include <QCryptographicHash>
17 #include <QStandardPaths>
18 #include <kconfig.h>
19 #include <kconfiggroup.h>
20 #include <klocalizedstring.h>		/* i18n */
21 #include <kmessagebox.h>
22 #include <ctype.h>
23 #include <stdlib.h>			/* strtol, atoi */
24 #include <unistd.h>			/* sleep(3) */
25 #include <algorithm>
26 #include "mydebug.h"
27 
28 /**
29  * Returns expression value for a tooltip.
30  */
31 template <class T>
formatPopupValue(const T * v)32 QString formatPopupValue(const T* v)
33 {
34     QString tip;
35 
36     if (!v->value().isEmpty())
37     {
38         tip += v->value();
39     }
40     else
41     {
42 	// no value: we use some hint
43         switch (v->m_varKind) {
44         case VarTree::VKstruct:
45             tip += "{...}";
46             break;
47         case VarTree::VKarray:
48             tip += "[...]";
49             break;
50         default:
51             tip += "?""?""?";	// 2 question marks in a row would be a trigraph
52             break;
53         }
54     }
55 
56     return tip;
57 }
58 
KDebugger(QWidget * parent,ExprWnd * localVars,ExprWnd * watchVars,QListWidget * backtrace)59 KDebugger::KDebugger(QWidget* parent,
60 		     ExprWnd* localVars,
61 		     ExprWnd* watchVars,
62 		     QListWidget* backtrace) :
63 	QObject(parent),
64 	m_ttyLevel(ttyFull),
65 	m_memoryFormat(MDTword | MDThex),
66 	m_memoryLength(16),
67 	m_haveExecutable(false),
68 	m_programActive(false),
69 	m_programRunning(false),
70 	m_sharedLibsListed(false),
71 	m_typeTable(0),
72 	m_programConfig(0),
73 	m_d(0),
74 	m_localVariables(*localVars),
75 	m_watchVariables(*watchVars),
76 	m_btWindow(*backtrace)
77 {
78     connect(&m_localVariables, SIGNAL(itemExpanded(QTreeWidgetItem*)),
79 	    SLOT(slotExpanding(QTreeWidgetItem*)));
80     connect(&m_watchVariables, SIGNAL(itemExpanded(QTreeWidgetItem*)),
81 	    SLOT(slotExpanding(QTreeWidgetItem*)));
82     connect(&m_localVariables, SIGNAL(editValueCommitted(VarTree*, const QString&)),
83 	    SLOT(slotValueEdited(VarTree*, const QString&)));
84     connect(&m_watchVariables, SIGNAL(editValueCommitted(VarTree*, const QString&)),
85 	    SLOT(slotValueEdited(VarTree*, const QString&)));
86 
87     connect(&m_btWindow, SIGNAL(currentRowChanged(int)), this, SLOT(gotoFrame(int)));
88 
89     emit updateUI();
90 }
91 
~KDebugger()92 KDebugger::~KDebugger()
93 {
94     if (m_programConfig != 0) {
95 	saveProgramSettings();
96 	m_programConfig->sync();
97 	delete m_programConfig;
98     }
99 
100     delete m_typeTable;
101 }
102 
103 
saveSettings(KConfig *)104 void KDebugger::saveSettings(KConfig* /*config*/)
105 {
106 }
107 
restoreSettings(KConfig *)108 void KDebugger::restoreSettings(KConfig* /*config*/)
109 {
110 }
111 
112 
113 //////////////////////////////////////////////////////////////////////
114 // external interface
115 
116 const char GeneralGroup[] = "General";
117 const char DebuggerCmdStr[] = "DebuggerCmdStr";
118 const char TTYLevelEntry[] = "TTYLevel";
119 const char KDebugger::DriverNameEntry[] = "DriverName";
120 
debugProgram(const QString & name,DebuggerDriver * driver)121 bool KDebugger::debugProgram(const QString& name,
122 			     DebuggerDriver* driver)
123 {
124     if (m_d != 0 && m_d->isRunning())
125     {
126 	QApplication::setOverrideCursor(Qt::WaitCursor);
127 
128 	stopDriver();
129 
130 	QApplication::restoreOverrideCursor();
131 
132 	if (m_d->isRunning() || m_haveExecutable) {
133 	    /* timed out! We can't really do anything useful now */
134 	    TRACE("timed out while waiting for gdb to die!");
135 	    return false;
136 	}
137 	delete m_d;
138 	m_d = 0;
139     }
140 
141     // wire up the driver
142     connect(driver, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
143 	    this, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)));
144     connect(driver, SIGNAL(finished(int, QProcess::ExitStatus)),
145 	    SLOT(gdbExited()));
146     connect(driver, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
147 	    SLOT(parse(CmdQueueItem*,const char*)));
148     connect(driver, SIGNAL(bytesWritten(qint64)), SIGNAL(updateUI()));
149     connect(driver, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
150     connect(driver, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
151     connect(driver, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
152     connect(&m_localVariables, SIGNAL(removingItem(VarTree*)),
153 	    driver, SLOT(dequeueCmdByVar(VarTree*)));
154     connect(&m_watchVariables, SIGNAL(removingItem(VarTree*)),
155 	    driver, SLOT(dequeueCmdByVar(VarTree*)));
156 
157     // create the program settings object
158     openProgramConfig(name);
159 
160     // get debugger command from per-program settings
161     if (m_programConfig != 0) {
162 	KConfigGroup g = m_programConfig->group(GeneralGroup);
163 	m_debuggerCmd = readDebuggerCmd(g);
164 	// get terminal emulation level
165 	m_ttyLevel = TTYLevel(g.readEntry(TTYLevelEntry, int(ttyFull)));
166     }
167     // the rest is read in later in the handler of DCexecutable
168 
169     m_d = driver;
170 
171     if (!startDriver()) {
172 	TRACE("startDriver failed");
173 	m_d = 0;
174 	return false;
175     }
176 
177     TRACE("before file cmd");
178     m_d->executeCmd(DCexecutable, name);
179     m_executable = name;
180 
181     // set remote target
182     if (!m_remoteDevice.isEmpty()) {
183 	m_d->executeCmd(DCtargetremote, m_remoteDevice);
184 	m_d->queueCmd(DCbt);
185 	m_d->queueCmd(DCinfothreads);
186 	m_d->queueCmdAgain(DCframe, 0);
187 	m_programActive = true;
188 	m_haveExecutable = true;
189     }
190 
191     // create a type table
192     m_typeTable = new ProgramTypeTable;
193     m_sharedLibsListed = false;
194 
195     emit updateUI();
196 
197     return true;
198 }
199 
shutdown()200 void KDebugger::shutdown()
201 {
202     // shut down debugger driver
203     if (m_d != 0 && m_d->isRunning())
204     {
205 	stopDriver();
206     }
207 }
208 
useCoreFile(QString corefile,bool batch)209 void KDebugger::useCoreFile(QString corefile, bool batch)
210 {
211     m_corefile = corefile;
212     if (!batch) {
213 	CmdQueueItem* cmd = loadCoreFile();
214 	cmd->m_byUser = true;
215     }
216 }
217 
setAttachPid(const QString & pid)218 void KDebugger::setAttachPid(const QString& pid)
219 {
220     m_attachedPid = pid;
221 }
222 
programRun()223 void KDebugger::programRun()
224 {
225     if (!isReady())
226 	return;
227 
228     // when program is active, but not a core file, continue
229     // otherwise run the program
230     if (m_programActive && m_corefile.isEmpty()) {
231 	// gdb command: continue
232 	m_d->executeCmdOnce(DCcont);
233     } else {
234 	// gdb command: run
235 	m_d->executeCmdOnce(DCrun);
236 	m_corefile = QString();
237 	m_programActive = true;
238     }
239     m_programRunning = true;
240 }
241 
attachProgram(const QString & pid)242 void KDebugger::attachProgram(const QString& pid)
243 {
244     if (!isReady())
245 	return;
246 
247     m_attachedPid = pid;
248     TRACE("Attaching to " + m_attachedPid);
249     m_d->executeCmd(DCattach, m_attachedPid);
250     m_programActive = true;
251     m_programRunning = true;
252 }
253 
programRunAgain()254 void KDebugger::programRunAgain()
255 {
256     if (canSingleStep()) {
257 	m_d->executeCmdOnce(DCrun);
258 	m_corefile = QString();
259 	m_programRunning = true;
260     }
261 }
262 
programStep()263 void KDebugger::programStep()
264 {
265     if (canSingleStep()) {
266 	m_d->executeCmdOnce(DCstep);
267 	m_programRunning = true;
268     }
269 }
270 
programNext()271 void KDebugger::programNext()
272 {
273     if (canSingleStep()) {
274 	m_d->executeCmdOnce(DCnext);
275 	m_programRunning = true;
276     }
277 }
278 
programStepi()279 void KDebugger::programStepi()
280 {
281     if (canSingleStep()) {
282 	m_d->executeCmdOnce(DCstepi);
283 	m_programRunning = true;
284     }
285 }
286 
programNexti()287 void KDebugger::programNexti()
288 {
289     if (canSingleStep()) {
290 	m_d->executeCmdOnce(DCnexti);
291 	m_programRunning = true;
292     }
293 }
294 
programFinish()295 void KDebugger::programFinish()
296 {
297     if (canSingleStep()) {
298 	m_d->executeCmdOnce(DCfinish);
299 	m_programRunning = true;
300     }
301 }
302 
programKill()303 void KDebugger::programKill()
304 {
305     if (haveExecutable() && isProgramActive()) {
306 	if (m_programRunning) {
307 	    m_d->interruptInferior();
308 	}
309 	// this is an emergency command; flush queues
310 	m_d->flushCommands(true);
311 	m_d->executeCmdOnce(DCkill);
312     }
313 }
314 
programDetach()315 void KDebugger::programDetach()
316 {
317     if (haveExecutable() && isProgramActive()) {
318 	if (m_programRunning) {
319 	    m_d->interruptInferior();
320 	}
321 	// this is an emergency command; flush queues
322 	m_d->flushCommands(true);
323 	m_d->executeCmdOnce(DCdetach);
324     }
325 }
326 
runUntil(const QString & fileName,int lineNo)327 bool KDebugger::runUntil(const QString& fileName, int lineNo)
328 {
329     if (isReady() && m_programActive && !m_programRunning) {
330 	// strip off directory part of file name
331 	QFileInfo fi(fileName);
332 	m_d->executeCmdOnce(DCuntil, fi.fileName(), lineNo);
333 	m_programRunning = true;
334 	return true;
335     } else {
336 	return false;
337     }
338 }
339 
programBreak()340 void KDebugger::programBreak()
341 {
342     if (m_haveExecutable && m_programRunning) {
343 	m_d->interruptInferior();
344     }
345 }
346 
programArgs(QWidget * parent)347 void KDebugger::programArgs(QWidget* parent)
348 {
349     if (m_haveExecutable) {
350 	QStringList allOptions = m_d->boolOptionList();
351 	PgmArgs dlg(parent, m_executable, m_envVars, allOptions);
352 	dlg.setArgs(m_programArgs);
353 	dlg.setWd(m_programWD);
354 	dlg.setOptions(m_boolOptions);
355 	if (dlg.exec()) {
356 	    updateProgEnvironment(dlg.args(), dlg.wd(),
357 				  dlg.envVars(), dlg.options());
358 	}
359     }
360 }
361 
programSettings(QWidget * parent)362 void KDebugger::programSettings(QWidget* parent)
363 {
364     if (!m_haveExecutable)
365 	return;
366 
367     ProgramSettings dlg(parent, m_executable);
368 
369     dlg.m_chooseDriver.setDebuggerCmd(m_debuggerCmd);
370     dlg.m_output.setTTYLevel(m_ttyLevel);
371 
372     if (dlg.exec() == QDialog::Accepted)
373     {
374 	m_debuggerCmd = dlg.m_chooseDriver.debuggerCmd();
375 	m_ttyLevel = TTYLevel(dlg.m_output.ttyLevel());
376     }
377 }
378 
setBreakpoint(QString file,int lineNo,const DbgAddr & address,bool temporary)379 bool KDebugger::setBreakpoint(QString file, int lineNo,
380 			      const DbgAddr& address, bool temporary)
381 {
382     if (!isReady()) {
383 	return false;
384     }
385 
386     BrkptIterator bp = breakpointByFilePos(file, lineNo, address);
387     if (bp == m_brkpts.end())
388     {
389 	/*
390 	 * No such breakpoint, so set a new one. If we have an address, we
391 	 * set the breakpoint exactly there. Otherwise we use the file name
392 	 * plus line no.
393 	 */
394 	Breakpoint* bp = new Breakpoint;
395 	bp->temporary = temporary;
396 
397 	if (address.isEmpty())
398 	{
399 	    bp->fileName = file;
400 	    bp->lineNo = lineNo;
401 	}
402 	else
403 	{
404 	    bp->address = address;
405 	}
406 	setBreakpoint(bp, false);
407     }
408     else
409     {
410 	/*
411 	 * If the breakpoint is disabled, enable it; if it's enabled,
412 	 * delete that breakpoint.
413 	 */
414 	if (bp->enabled) {
415 	    deleteBreakpoint(bp);
416 	} else {
417 	    enableDisableBreakpoint(bp);
418 	}
419     }
420     return true;
421 }
422 
setBreakpoint(Breakpoint * bp,bool queueOnly)423 void KDebugger::setBreakpoint(Breakpoint* bp, bool queueOnly)
424 {
425     CmdQueueItem* cmd = executeBreakpoint(bp, queueOnly);
426     cmd->m_brkpt = bp;	// used in newBreakpoint()
427 }
428 
executeBreakpoint(const Breakpoint * bp,bool queueOnly)429 CmdQueueItem* KDebugger::executeBreakpoint(const Breakpoint* bp, bool queueOnly)
430 {
431     CmdQueueItem* cmd;
432     if (!bp->text.isEmpty())
433     {
434 	/*
435 	 * The breakpoint was set using the text box in the breakpoint
436 	 * list. This is the only way in which watchpoints are set.
437 	 */
438 	if (bp->type == Breakpoint::watchpoint) {
439 	    cmd = m_d->executeCmd(DCwatchpoint, bp->text);
440 	} else {
441 	    cmd = m_d->executeCmd(DCbreaktext, bp->text);
442 	}
443     }
444     else if (bp->address.isEmpty())
445     {
446 	// strip off directory part of file name
447 	QString file = QFileInfo(bp->fileName).fileName();
448 	if (queueOnly) {
449 	    cmd = m_d->queueCmd(bp->temporary ? DCtbreakline : DCbreakline,
450 				file, bp->lineNo);
451 	} else {
452 	    cmd = m_d->executeCmd(bp->temporary ? DCtbreakline : DCbreakline,
453 				  file, bp->lineNo);
454 	}
455     }
456     else
457     {
458 	if (queueOnly) {
459 	    cmd = m_d->queueCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
460 				bp->address.asString());
461 	} else {
462 	    cmd = m_d->executeCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
463 				  bp->address.asString());
464 	}
465     }
466     return cmd;
467 }
468 
infoLine(QString file,int lineNo,const DbgAddr & addr)469 bool KDebugger::infoLine(QString file, int lineNo, const DbgAddr& addr)
470 {
471     if (isReady() && !m_programRunning) {
472 	CmdQueueItem* cmd = m_d->executeCmd(DCinfoline, file, lineNo);
473 	cmd->m_addr = addr;
474 	return true;
475     } else {
476 	return false;
477     }
478 }
479 
enableDisableBreakpoint(QString file,int lineNo,const DbgAddr & address)480 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo,
481 					const DbgAddr& address)
482 {
483     BrkptIterator bp = breakpointByFilePos(file, lineNo, address);
484     return enableDisableBreakpoint(bp);
485 }
486 
enableDisableBreakpoint(BrkptIterator bp)487 bool KDebugger::enableDisableBreakpoint(BrkptIterator bp)
488 {
489     if (bp == m_brkpts.end())
490 	return false;
491 
492     /*
493      * Toggle enabled/disabled state.
494      *
495      * The driver is not bothered if we are modifying an orphaned
496      * breakpoint.
497      */
498     if (!bp->isOrphaned()) {
499 	if (!canChangeBreakpoints()) {
500 	    return false;
501 	}
502 	m_d->executeCmd(bp->enabled ? DCdisable : DCenable, bp->id);
503     } else {
504 	bp->enabled = !bp->enabled;
505 	emit breakpointsChanged();
506     }
507     return true;
508 }
509 
conditionalBreakpoint(BrkptIterator bp,const QString & condition,int ignoreCount)510 bool KDebugger::conditionalBreakpoint(BrkptIterator bp,
511 				      const QString& condition,
512 				      int ignoreCount)
513 {
514     if (bp == m_brkpts.end())
515 	return false;
516 
517     /*
518      * Change the condition and ignore count.
519      *
520      * The driver is not bothered if we are removing an orphaned
521      * breakpoint.
522      */
523 
524     if (!bp->isOrphaned()) {
525 	if (!canChangeBreakpoints()) {
526 	    return false;
527 	}
528 
529 	bool changed = false;
530 
531 	if (bp->condition != condition) {
532 	    // change condition
533 	    m_d->executeCmd(DCcondition, condition, bp->id);
534 	    changed = true;
535 	}
536 	if (bp->ignoreCount != ignoreCount) {
537 	    // change ignore count
538 	    m_d->executeCmd(DCignore, bp->id, ignoreCount);
539 	    changed = true;
540 	}
541 	if (changed) {
542 	    // get the changes
543 	    m_d->queueCmd(DCinfobreak);
544 	}
545     } else {
546 	bp->condition = condition;
547 	bp->ignoreCount = ignoreCount;
548 	emit breakpointsChanged();
549     }
550     return true;
551 }
552 
deleteBreakpoint(BrkptIterator bp)553 bool KDebugger::deleteBreakpoint(BrkptIterator bp)
554 {
555     if (bp == m_brkpts.end())
556 	return false;
557 
558     /*
559      * Remove the breakpoint.
560      *
561      * The driver is not bothered if we are removing an orphaned
562      * breakpoint.
563      */
564     if (!bp->isOrphaned()) {
565 	if (!canChangeBreakpoints()) {
566 	    return false;
567 	}
568 	m_d->executeCmd(DCdelete, bp->id);
569     } else {
570 	m_brkpts.erase(bp);
571 	emit breakpointsChanged();
572     }
573     return false;
574 }
575 
canSingleStep()576 bool KDebugger::canSingleStep()
577 {
578     return isReady() && m_programActive && !m_programRunning;
579 }
580 
canChangeBreakpoints()581 bool KDebugger::canChangeBreakpoints()
582 {
583     return isReady() && !m_programRunning;
584 }
585 
canStart()586 bool KDebugger::canStart()
587 {
588     return isReady() && !m_programActive;
589 }
590 
isReady() const591 bool KDebugger::isReady() const
592 {
593     return m_haveExecutable &&
594 	m_d != 0 && m_d->canExecuteImmediately();
595 }
596 
isIdle() const597 bool KDebugger::isIdle() const
598 {
599     return m_d == 0 || m_d->isIdle();
600 }
601 
602 
603 //////////////////////////////////////////////////////////
604 // debugger driver
605 
startDriver()606 bool KDebugger::startDriver()
607 {
608     emit debuggerStarting();		/* must set m_inferiorTerminal */
609 
610     /*
611      * If the per-program command string is empty, use the global setting
612      * (which might also be empty, in which case the driver uses its
613      * default).
614      */
615     m_explicitKill = false;
616     if (!m_d->startup(m_debuggerCmd)) {
617 	return false;
618     }
619 
620     /*
621      * If we have an output terminal, we use it. Otherwise we will run the
622      * program with input and output redirected to /dev/null. Other
623      * redirections are also necessary depending on the tty emulation
624      * level.
625      */
626     int redirect = RDNstdin|RDNstdout|RDNstderr;	/* redirect everything */
627     if (!m_inferiorTerminal.isEmpty()) {
628 	switch (m_ttyLevel) {
629 	default:
630 	case ttyNone:
631 	    // redirect everything
632 	    break;
633 	case ttySimpleOutputOnly:
634 	    redirect = RDNstdin;
635 	    break;
636 	case ttyFull:
637 	    redirect = 0;
638 	    break;
639 	}
640     }
641     m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
642 
643     return true;
644 }
645 
stopDriver()646 void KDebugger::stopDriver()
647 {
648     m_explicitKill = true;
649 
650     if (m_attachedPid.isEmpty()) {
651 	m_d->terminate();
652     } else {
653 	m_d->detachAndTerminate();
654     }
655 
656     /*
657      * We MUST wait until the slot gdbExited() has been called. But to
658      * avoid a deadlock, we wait only for some certain maximum time. Should
659      * this timeout be reached, the only reasonable thing one could do then
660      * is exiting kdbg.
661      */
662     QApplication::processEvents(QEventLoop::AllEvents, 1000);
663     int maxTime = 20;			/* about 20 seconds */
664     while (m_haveExecutable && maxTime > 0) {
665 	// give gdb time to die (and send a SIGCLD)
666 	::sleep(1);
667 	--maxTime;
668 	QApplication::processEvents(QEventLoop::AllEvents, 1000);
669     }
670 }
671 
gdbExited()672 void KDebugger::gdbExited()
673 {
674     /*
675      * Save settings, but only if gdb has already processed "info line
676      * main", otherwise we would save an empty config file, because it
677      * isn't read in until then!
678      */
679     if (m_programConfig != 0) {
680 	if (m_haveExecutable) {
681 	    saveProgramSettings();
682 	    m_programConfig->sync();
683 	}
684 	delete m_programConfig;
685 	m_programConfig = 0;
686     }
687 
688     // erase types
689     delete m_typeTable;
690     m_typeTable = 0;
691 
692     if (m_explicitKill) {
693 	TRACE(m_d->driverName() + " exited normally");
694     } else {
695 	QString msg = i18n("%1 exited unexpectedly.\n"
696 			   "Restart the session (e.g. with File|Load Executable).");
697 	KMessageBox::error(parentWidget(), msg.arg(m_d->driverName()));
698     }
699 
700     // reset state
701     m_haveExecutable = false;
702     m_executable = "";
703     m_programActive = false;
704     m_programRunning = false;
705     m_explicitKill = false;
706     m_debuggerCmd = QString();		/* use global setting at next start! */
707     m_attachedPid = QString();		/* we are no longer attached to a process */
708     m_ttyLevel = ttyFull;
709     m_brkpts.clear();
710 
711     // erase PC
712     emit updatePC(QString(), -1, DbgAddr(), 0);
713 }
714 
getConfigForExe(const QString & name)715 QString KDebugger::getConfigForExe(const QString& name)
716 {
717     QFileInfo fi(name);
718     QString dir = fi.absolutePath();
719 
720     // The session file for the given executable consists of
721     // a hash of the directory, followed by the program name.
722     // Assume that the first 15 positions of the hash are unique;
723     // this keeps the file names short.
724     QCryptographicHash dirDigest(QCryptographicHash::Md5);
725     dirDigest.addData(dir.toUtf8());
726     QString hash = dirDigest.result().toBase64();
727     hash.replace('/', QString());	// avoid directory separators
728     return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)
729 		+ "/sessions/"
730 		+ hash.left(15) + "-" + fi.fileName();
731 }
732 
openProgramConfig(const QString & name)733 void KDebugger::openProgramConfig(const QString& name)
734 {
735     ASSERT(m_programConfig == 0);
736 
737     QString pgmConfigFile = getConfigForExe(name);
738 
739     m_programConfig = new KConfig(pgmConfigFile);
740 
741     // this leaves a clue behind in the config file which
742     // executable it applies to; it is mostly intended for
743     // users peeking into the file
744     KConfigGroup g = m_programConfig->group(GeneralGroup);
745     g.writeEntry("ExecutableFile", name);
746 }
747 
748 const char EnvironmentGroup[] = "Environment";
749 const char WatchGroup[] = "Watches";
750 const char FileVersion[] = "FileVersion";
751 const char ProgramArgs[] = "ProgramArgs";
752 const char WorkingDirectory[] = "WorkingDirectory";
753 const char OptionsSelected[] = "OptionsSelected";
754 const char Variable[] = "Var%d";
755 const char Value[] = "Value%d";
756 const char ExprFmt[] = "Expr%d";
757 
saveProgramSettings()758 void KDebugger::saveProgramSettings()
759 {
760     ASSERT(m_programConfig != 0);
761     KConfigGroup gg = m_programConfig->group(GeneralGroup);
762     gg.writeEntry(FileVersion, 1);
763     gg.writeEntry(ProgramArgs, m_programArgs);
764     gg.writeEntry(WorkingDirectory, m_programWD);
765     gg.writeEntry(OptionsSelected, m_boolOptions.toList());
766     gg.writeEntry(DebuggerCmdStr, m_debuggerCmd);
767     gg.writeEntry(TTYLevelEntry, int(m_ttyLevel));
768     QString driverName;
769     if (m_d != 0)
770 	driverName = m_d->driverName();
771     gg.writeEntry(DriverNameEntry, driverName);
772 
773     // write environment variables
774     m_programConfig->deleteGroup(EnvironmentGroup);
775     KConfigGroup eg = m_programConfig->group(EnvironmentGroup);
776     QString varName;
777     QString varValue;
778     int i = 0;
779     for (std::map<QString,QString>::iterator it = m_envVars.begin(); it != m_envVars.end(); ++it, ++i)
780     {
781 	varName.sprintf(Variable, i);
782 	varValue.sprintf(Value, i);
783 	eg.writeEntry(varName, it->first);
784 	eg.writeEntry(varValue, it->second);
785     }
786 
787     saveBreakpoints(m_programConfig);
788 
789     // watch expressions
790     // first get rid of whatever was in this group
791     m_programConfig->deleteGroup(WatchGroup);
792     // then start a new group
793     KConfigGroup wg = m_programConfig->group(WatchGroup);
794     int watchNum = 0;
795     foreach (QString expr, m_watchVariables.exprList()) {
796 	varName.sprintf(ExprFmt, watchNum++);
797 	wg.writeEntry(varName, expr);
798     }
799 
800     // give others a chance
801     emit saveProgramSpecific(m_programConfig);
802 }
803 
overrideProgramArguments(const QString & args)804 void KDebugger::overrideProgramArguments(const QString& args)
805 {
806     ASSERT(m_programConfig != 0);
807     KConfigGroup g = m_programConfig->group(GeneralGroup);
808     g.writeEntry(ProgramArgs, args);
809 }
810 
restoreProgramSettings()811 void KDebugger::restoreProgramSettings()
812 {
813     ASSERT(m_programConfig != 0);
814     KConfigGroup gg = m_programConfig->group(GeneralGroup);
815     /*
816      * We ignore file version for now we will use it in the future to
817      * distinguish different versions of this configuration file.
818      */
819     // m_debuggerCmd has been read in already
820     // m_ttyLevel has been read in already
821     QString pgmArgs = gg.readEntry(ProgramArgs);
822     QString pgmWd = gg.readEntry(WorkingDirectory);
823     QSet<QString> boolOptions = QSet<QString>::fromList(gg.readEntry(OptionsSelected, QStringList()));
824     m_boolOptions.clear();
825 
826     // read environment variables
827     KConfigGroup eg = m_programConfig->group(EnvironmentGroup);
828     m_envVars.clear();
829     std::map<QString,EnvVar> pgmVars;
830     QString varName;
831     QString varValue;
832     for (int i = 0;; ++i) {
833 	varName.sprintf(Variable, i);
834 	varValue.sprintf(Value, i);
835 	if (!eg.hasKey(varName)) {
836 	    /* entry not present, assume that we've hit them all */
837 	    break;
838 	}
839 	QString name = eg.readEntry(varName, QString());
840 	if (name.isEmpty()) {
841 	    // skip empty names
842 	    continue;
843 	}
844 	EnvVar* var = &pgmVars[name];
845 	var->value = eg.readEntry(varValue, QString());
846 	var->status = EnvVar::EVnew;
847     }
848 
849     updateProgEnvironment(pgmArgs, pgmWd, pgmVars, boolOptions);
850 
851     restoreBreakpoints(m_programConfig);
852 
853     // watch expressions
854     KConfigGroup wg = m_programConfig->group(WatchGroup);
855     m_watchVariables.clear();
856     for (int i = 0;; ++i) {
857 	varName.sprintf(ExprFmt, i);
858 	if (!wg.hasKey(varName)) {
859 	    /* entry not present, assume that we've hit them all */
860 	    break;
861 	}
862 	QString expr = wg.readEntry(varName, QString());
863 	if (expr.isEmpty()) {
864 	    // skip empty expressions
865 	    continue;
866 	}
867 	addWatch(expr);
868     }
869 
870     // give others a chance
871     emit restoreProgramSpecific(m_programConfig);
872 }
873 
874 /**
875  * Reads the debugger command line from the program settings. The config
876  * group must have been set by the caller.
877  */
readDebuggerCmd(const KConfigGroup & g)878 QString KDebugger::readDebuggerCmd(const KConfigGroup& g)
879 {
880     QString debuggerCmd = g.readEntry(DebuggerCmdStr);
881 
882     // always let the user confirm the debugger cmd if we are root
883     if (::geteuid() == 0)
884     {
885 	if (!debuggerCmd.isEmpty()) {
886 	    QString msg = i18n(
887 		"The settings for this program specify "
888 		"the following debugger command:\n%1\n"
889 		"Shall this command be used?");
890 	    if (KMessageBox::warningYesNo(parentWidget(), msg.arg(debuggerCmd))
891 		!= KMessageBox::Yes)
892 	    {
893 		// don't use it
894 		debuggerCmd = QString();
895 	    }
896 	}
897     }
898     return debuggerCmd;
899 }
900 
901 /*
902  * Breakpoints are saved one per group.
903  */
904 const char BPGroup[] = "Breakpoint %d";
905 const char File[] = "File";
906 const char Line[] = "Line";
907 const char Text[] = "Text";
908 const char Address[] = "Address";
909 const char Temporary[] = "Temporary";
910 const char Enabled[] = "Enabled";
911 const char Condition[] = "Condition";
912 
saveBreakpoints(KConfig * config)913 void KDebugger::saveBreakpoints(KConfig* config)
914 {
915     QString groupName;
916     int i = 0;
917     for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
918     {
919 	if (bp->type == Breakpoint::watchpoint)
920 	    continue;			/* don't save watchpoints */
921 	groupName.sprintf(BPGroup, i++);
922 
923 	/* remove remmants */
924 	config->deleteGroup(groupName);
925 
926 	KConfigGroup g = config->group(groupName);
927 	if (!bp->text.isEmpty()) {
928 	    /*
929 	     * The breakpoint was set using the text box in the breakpoint
930 	     * list. We do not save the location by filename+line number,
931 	     * but instead honor what the user typed (a function name, for
932 	     * example, which could move between sessions).
933 	     */
934 	    g.writeEntry(Text, bp->text);
935 	} else if (!bp->fileName.isEmpty()) {
936 	    g.writeEntry(File, bp->fileName);
937 	    g.writeEntry(Line, bp->lineNo);
938 	    /*
939 	     * Addresses are hardly correct across sessions, so we don't
940 	     * save it.
941 	     */
942 	} else {
943 	    g.writeEntry(Address, bp->address.asString());
944 	}
945 	g.writeEntry(Temporary, bp->temporary);
946 	g.writeEntry(Enabled, bp->enabled);
947 	if (!bp->condition.isEmpty())
948 	    g.writeEntry(Condition, bp->condition);
949 	// we do not save the ignore count
950     }
951     // delete remaining groups
952     // we recognize that a group is present if there is an Enabled entry
953     for (;; i++) {
954 	groupName.sprintf(BPGroup, i);
955 	if (!config->group(groupName).hasKey(Enabled)) {
956 	    /* group not present, assume that we've hit them all */
957 	    break;
958 	}
959 	config->deleteGroup(groupName);
960     }
961 }
962 
restoreBreakpoints(KConfig * config)963 void KDebugger::restoreBreakpoints(KConfig* config)
964 {
965     QString groupName;
966     /*
967      * We recognize the end of the list if there is no Enabled entry
968      * present.
969      */
970     for (int i = 0;; i++) {
971 	groupName.sprintf(BPGroup, i);
972 	KConfigGroup g = config->group(groupName);
973 	if (!g.hasKey(Enabled)) {
974 	    /* group not present, assume that we've hit them all */
975 	    break;
976 	}
977 	Breakpoint* bp = new Breakpoint;
978 	bp->fileName = g.readEntry(File);
979 	bp->lineNo = g.readEntry(Line, -1);
980 	bp->text = g.readEntry(Text);
981 	bp->address = g.readEntry(Address);
982 	// check consistency
983 	if ((bp->fileName.isEmpty() || bp->lineNo < 0) &&
984 	    bp->text.isEmpty() &&
985 	    bp->address.isEmpty())
986 	{
987 	    delete bp;
988 	    continue;
989 	}
990 	bp->enabled = g.readEntry(Enabled, true);
991 	bp->temporary = g.readEntry(Temporary, false);
992 	bp->condition = g.readEntry(Condition);
993 
994 	/*
995 	 * Add the breakpoint.
996 	 */
997 	setBreakpoint(bp, false);
998 	// the new breakpoint is disabled or conditionalized later
999 	// in newBreakpoint()
1000     }
1001     m_d->queueCmd(DCinfobreak);
1002 }
1003 
1004 
1005 // parse output of command cmd
parse(CmdQueueItem * cmd,const char * output)1006 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
1007 {
1008     ASSERT(cmd != 0);			/* queue mustn't be empty */
1009 
1010     TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
1011 
1012     switch (cmd->m_cmd) {
1013     case DCtargetremote:
1014 	// the output (if any) is uninteresting
1015     case DCsetargs:
1016     case DCtty:
1017 	// there is no output
1018     case DCsetenv:
1019     case DCunsetenv:
1020     case DCsetoption:
1021 	/* if value is empty, we see output, but we don't care */
1022 	break;
1023     case DCcd:
1024 	/* display gdb's message in the status bar */
1025 	m_d->parseChangeWD(output, m_statusMessage);
1026 	emit updateStatusMessage();
1027 	break;
1028     case DCinitialize:
1029 	break;
1030     case DCexecutable:
1031 	if (m_d->parseChangeExecutable(output, m_statusMessage))
1032 	{
1033 	    // success; restore breakpoints etc.
1034 	    if (m_programConfig != 0) {
1035 		restoreProgramSettings();
1036 	    }
1037 	    // load file containing main() or core file
1038 	    if (!m_corefile.isEmpty())
1039 	    {
1040 		// load core file
1041 		loadCoreFile();
1042 	    }
1043 	    else if (!m_attachedPid.isEmpty())
1044 	    {
1045 		m_d->queueCmd(DCattach, m_attachedPid);
1046 		m_programActive = true;
1047 		m_programRunning = true;
1048 	    }
1049 	    else if (!m_remoteDevice.isEmpty())
1050 	    {
1051 		// handled elsewhere
1052 	    }
1053 	    else
1054 	    {
1055 		m_d->queueCmdAgain(DCinfolinemain);
1056 	    }
1057 	    if (!m_statusMessage.isEmpty())
1058 		emit updateStatusMessage();
1059 	} else {
1060 	    QString msg = m_d->driverName() + ": " + m_statusMessage;
1061 	    KMessageBox::sorry(parentWidget(), msg);
1062 	    m_executable = "";
1063 	    m_corefile = "";		/* don't process core file */
1064 	    m_haveExecutable = false;
1065 	}
1066 	break;
1067     case DCcorefile:
1068 	// in any event we have an executable at this point
1069 	m_haveExecutable = true;
1070 	if (m_d->parseCoreFile(output)) {
1071 	    // loading a core is like stopping at a breakpoint
1072 	    m_programActive = true;
1073 	    handleRunCommands(output);
1074 	    // do not reset m_corefile
1075 	} else {
1076 	    // report error
1077 	    QString msg = m_d->driverName() + ": " + QString(output);
1078 	    KMessageBox::sorry(parentWidget(), msg);
1079 
1080 	    // if core file was loaded from command line, revert to info line main
1081 	    if (!cmd->m_byUser) {
1082 		m_d->queueCmdAgain(DCinfolinemain);
1083 	    }
1084 	    m_corefile = QString();	/* core file not available any more */
1085 	}
1086 	break;
1087     case DCinfolinemain:
1088 	// ignore the output, marked file info follows
1089 	m_haveExecutable = true;
1090 	break;
1091     case DCinfolocals:
1092 	// parse local variables
1093 	if (output[0] != '\0') {
1094 	    handleLocals(output);
1095 	}
1096 	break;
1097     case DCinforegisters:
1098 	handleRegisters(output);
1099 	break;
1100     case DCexamine:
1101 	handleMemoryDump(output);
1102 	break;
1103     case DCinfoline:
1104 	handleInfoLine(cmd, output);
1105 	break;
1106     case DCdisassemble:
1107 	handleDisassemble(cmd, output);
1108 	break;
1109     case DCframe:
1110 	handleFrameChange(output);
1111 	updateAllExprs();
1112 	break;
1113     case DCbt:
1114 	handleBacktrace(output);
1115 	updateAllExprs();
1116 	break;
1117     case DCprint:
1118 	handlePrint(cmd, output);
1119 	break;
1120     case DCprintPopup:
1121 	handlePrintPopup(cmd, output);
1122 	break;
1123     case DCprintDeref:
1124 	handlePrintDeref(cmd, output);
1125 	break;
1126     case DCattach:
1127 	m_haveExecutable = true;
1128 	// fall through
1129     case DCrun:
1130     case DCcont:
1131     case DCstep:
1132     case DCstepi:
1133     case DCnext:
1134     case DCnexti:
1135     case DCfinish:
1136     case DCuntil:
1137     case DCthread:
1138 	handleRunCommands(output);
1139 	break;
1140     case DCkill:
1141     case DCdetach:
1142 	m_programRunning = m_programActive = false;
1143 	// erase PC
1144 	emit updatePC(QString(), -1, DbgAddr(), 0);
1145 	break;
1146     case DCbreaktext:
1147     case DCbreakline:
1148     case DCtbreakline:
1149     case DCbreakaddr:
1150     case DCtbreakaddr:
1151     case DCwatchpoint:
1152 	newBreakpoint(cmd, output);
1153 	// fall through
1154     case DCdelete:
1155     case DCenable:
1156     case DCdisable:
1157 	// these commands need immediate response
1158 	m_d->queueCmdPrio(DCinfobreak);
1159 	break;
1160     case DCinfobreak:
1161 	// note: this handler must not enqueue a command, since
1162 	// DCinfobreak is used at various different places.
1163 	updateBreakList(output);
1164 	break;
1165     case DCfindType:
1166 	handleFindType(cmd, output);
1167 	break;
1168     case DCprintStruct:
1169     case DCprintQStringStruct:
1170     case DCprintWChar:
1171 	handlePrintStruct(cmd, output);
1172 	break;
1173     case DCinfosharedlib:
1174 	handleSharedLibs(output);
1175 	break;
1176     case DCcondition:
1177     case DCignore:
1178 	// we are not interested in the output
1179 	break;
1180     case DCinfothreads:
1181 	handleThreadList(output);
1182 	break;
1183     case DCsetpc:
1184 	handleSetPC(output);
1185 	break;
1186     case DCsetvariable:
1187 	handleSetVariable(cmd, output);
1188 	break;
1189     }
1190 }
1191 
backgroundUpdate()1192 void KDebugger::backgroundUpdate()
1193 {
1194     /*
1195      * If there are still expressions that need to be updated, then do so.
1196      */
1197     if (m_programActive)
1198 	evalExpressions();
1199 }
1200 
handleRunCommands(const char * output)1201 void KDebugger::handleRunCommands(const char* output)
1202 {
1203     uint flags = m_d->parseProgramStopped(output, !m_corefile.isEmpty(),
1204 					  m_statusMessage);
1205     emit updateStatusMessage();
1206 
1207     m_programActive = flags & DebuggerDriver::SFprogramActive;
1208 
1209     // refresh files if necessary
1210     if (flags & DebuggerDriver::SFrefreshSource) {
1211 	TRACE("re-reading files");
1212 	emit executableUpdated();
1213     }
1214 
1215     /*
1216      * Try to set any orphaned breakpoints now.
1217      */
1218     for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
1219     {
1220 	if (bp->isOrphaned()) {
1221 	    TRACE(QString("re-trying brkpt loc: %2 file: %3 line: %1")
1222 		    .arg(bp->lineNo).arg(bp->location, bp->fileName));
1223 	    CmdQueueItem* cmd = executeBreakpoint(&*bp, true);
1224 	    cmd->m_existingBrkpt = bp->id;	// used in newBreakpoint()
1225 	    flags |= DebuggerDriver::SFrefreshBreak;
1226 	}
1227     }
1228 
1229     /*
1230      * If we stopped at a breakpoint, we must update the breakpoint list
1231      * because the hit count changes. Also, if the breakpoint was temporary
1232      * it would go away now.
1233      */
1234     if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
1235 	stopMayChangeBreakList())
1236     {
1237 	m_d->queueCmd(DCinfobreak);
1238     }
1239 
1240     /*
1241      * If we haven't listed the shared libraries yet, do so. We must do
1242      * this before we emit any commands that list variables, since the type
1243      * libraries depend on the shared libraries.
1244      */
1245     if (!m_sharedLibsListed) {
1246 	// must be a high-priority command!
1247 	m_d->executeCmd(DCinfosharedlib);
1248     }
1249 
1250     // get the backtrace if the program is running
1251     if (m_programActive) {
1252 	m_d->queueCmd(DCbt);
1253     } else {
1254 	// program finished: erase PC
1255 	emit updatePC(QString(), -1, DbgAddr(), 0);
1256 	// dequeue any commands in the queues
1257 	m_d->flushCommands();
1258     }
1259 
1260     /* Update threads list */
1261     if (m_programActive && (flags & DebuggerDriver::SFrefreshThreads)) {
1262 	m_d->queueCmd(DCinfothreads);
1263     }
1264 
1265     m_programRunning = false;
1266     emit programStopped();
1267 }
1268 
slotInferiorRunning()1269 void KDebugger::slotInferiorRunning()
1270 {
1271     m_programRunning = true;
1272 }
1273 
updateAllExprs()1274 void KDebugger::updateAllExprs()
1275 {
1276     if (!m_programActive)
1277 	return;
1278 
1279     // retrieve local variables
1280     m_d->queueCmd(DCinfolocals);
1281 
1282     // retrieve registers
1283     m_d->queueCmd(DCinforegisters);
1284 
1285     // get new memory dump
1286     if (!m_memoryStartExpression.isEmpty()) {
1287 	queueMemoryDump(false, true);
1288     }
1289 
1290     // update watch expressions
1291     foreach (QString expr, m_watchVariables.exprList()) {
1292 	m_watchEvalExpr.push_back(expr);
1293     }
1294 }
1295 
updateProgEnvironment(const QString & args,const QString & wd,const std::map<QString,EnvVar> & newVars,const QSet<QString> & newOptions)1296 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
1297 				      const std::map<QString,EnvVar>& newVars,
1298 				      const QSet<QString>& newOptions)
1299 {
1300     m_programArgs = args;
1301     m_d->executeCmd(DCsetargs, m_programArgs);
1302     TRACE("new pgm args: " + m_programArgs + "\n");
1303 
1304     m_programWD = wd.trimmed();
1305     if (!m_programWD.isEmpty()) {
1306 	m_d->executeCmd(DCcd, m_programWD);
1307 	TRACE("new wd: " + m_programWD + "\n");
1308     }
1309 
1310     // update environment variables
1311     for (std::map<QString,EnvVar>::const_iterator i = newVars.begin(); i != newVars.end(); ++i)
1312     {
1313 	QString var = i->first;
1314 	const EnvVar* val = &i->second;
1315 	switch (val->status) {
1316 	case EnvVar::EVnew:
1317 	case EnvVar::EVdirty:
1318 	    m_envVars[var] = val->value;
1319 	    // update value
1320 	    m_d->executeCmd(DCsetenv, var, val->value);
1321 	    break;
1322 	case EnvVar::EVdeleted:
1323 	    // delete value
1324 	    m_d->executeCmd(DCunsetenv, var);
1325 	    m_envVars.erase(var);
1326 	    break;
1327 	default:
1328 	    ASSERT(false);
1329 	case EnvVar::EVclean:
1330 	    // variable not changed
1331 	    break;
1332 	}
1333     }
1334 
1335     // update options
1336     foreach (QString opt, newOptions - m_boolOptions)
1337     {
1338 	// option is not set, set it
1339 	m_d->executeCmd(DCsetoption, opt, 1);
1340     }
1341     foreach (QString opt, m_boolOptions - newOptions)
1342     {
1343 	// option is set, unset it
1344 	m_d->executeCmd(DCsetoption, opt, 0);
1345     }
1346     m_boolOptions = newOptions;
1347 }
1348 
handleLocals(const char * output)1349 void KDebugger::handleLocals(const char* output)
1350 {
1351     // retrieve old list of local variables
1352     QStringList oldVars = m_localVariables.exprList();
1353 
1354     /*
1355      *  Get local variables.
1356      */
1357     std::list<ExprValue*> newVars;
1358     parseLocals(output, newVars);
1359 
1360     /*
1361      * Clear any old VarTree item pointers, so that later we don't access
1362      * dangling pointers.
1363      */
1364     m_localVariables.clearPendingUpdates();
1365 
1366     /*
1367      * Match old variables against new ones.
1368      */
1369     for (QStringList::ConstIterator n = oldVars.begin(); n != oldVars.end(); ++n) {
1370 	// lookup this variable in the list of new variables
1371 	std::list<ExprValue*>::iterator v = newVars.begin();
1372 	while (v != newVars.end() && (*v)->m_name != *n)
1373 	    ++v;
1374 	if (v == newVars.end()) {
1375 	    // old variable not in the new variables
1376 	    TRACE("old var deleted: " + *n);
1377 	    VarTree* v = m_localVariables.topLevelExprByName(*n);
1378 	    if (v != 0) {
1379 		m_localVariables.removeExpr(v);
1380 	    }
1381 	} else {
1382 	    // variable in both old and new lists: update
1383 	    TRACE("update var: " + *n);
1384 	    m_localVariables.updateExpr(*v, *m_typeTable);
1385 	    // remove the new variable from the list
1386 	    delete *v;
1387 	    newVars.erase(v);
1388 	}
1389     }
1390     // insert all remaining new variables
1391     while (!newVars.empty())
1392     {
1393 	ExprValue* v = newVars.front();
1394 	TRACE("new var: " + v->m_name);
1395 	m_localVariables.insertExpr(v, *m_typeTable);
1396 	delete v;
1397 	newVars.pop_front();
1398     }
1399 }
1400 
parseLocals(const char * output,std::list<ExprValue * > & newVars)1401 void KDebugger::parseLocals(const char* output, std::list<ExprValue*>& newVars)
1402 {
1403     std::list<ExprValue*> vars;
1404     m_d->parseLocals(output, vars);
1405 
1406     QString origName;			/* used in renaming variables */
1407     while (!vars.empty())
1408     {
1409 	ExprValue* variable = vars.front();
1410 	vars.pop_front();
1411 	/*
1412 	 * When gdb prints local variables, those from the innermost block
1413 	 * come first. We run through the list of already parsed variables
1414 	 * to find duplicates (ie. variables that hide local variables from
1415 	 * a surrounding block). We keep the name of the inner variable, but
1416 	 * rename those from the outer block so that, when the value is
1417 	 * updated in the window, the value of the variable that is
1418 	 * _visible_ changes the color!
1419 	 */
1420 	int block = 0;
1421 	origName = variable->m_name;
1422 	for (std::list<ExprValue*>::iterator v = newVars.begin(); v != newVars.end(); ++v) {
1423 	    if (variable->m_name == (*v)->m_name) {
1424 		// we found a duplicate, change name
1425 		block++;
1426 		QString newName = origName + " (" + QString().setNum(block) + ")";
1427 		variable->m_name = newName;
1428 	    }
1429 	}
1430 	newVars.push_back(variable);
1431     }
1432 }
1433 
handlePrint(CmdQueueItem * cmd,const char * output)1434 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1435 {
1436     ASSERT(cmd->m_expr != 0);
1437 
1438     ExprValue* variable = m_d->parsePrintExpr(output, true);
1439     if (variable == 0)
1440 	return false;
1441 
1442     // set expression "name"
1443     variable->m_name = cmd->m_expr->getText();
1444 
1445     {
1446 	TRACE("update expr: " + cmd->m_expr->getText());
1447 	cmd->m_exprWnd->updateExpr(cmd->m_expr, variable, *m_typeTable);
1448 	delete variable;
1449     }
1450 
1451     evalExpressions();			/* enqueue dereferenced pointers */
1452 
1453     return true;
1454 }
1455 
handlePrintPopup(CmdQueueItem * cmd,const char * output)1456 bool KDebugger::handlePrintPopup(CmdQueueItem* cmd, const char* output)
1457 {
1458     ExprValue* value = m_d->parsePrintExpr(output, false);
1459     if (value == 0)
1460 	return false;
1461 
1462     TRACE("<" + cmd->m_popupExpr + "> = " + value->m_value);
1463 
1464     // construct the tip, m_popupExpr contains the variable name
1465     QString tip = cmd->m_popupExpr + " = " + formatPopupValue(value);
1466     emit valuePopup(tip);
1467 
1468     return true;
1469 }
1470 
handlePrintDeref(CmdQueueItem * cmd,const char * output)1471 bool KDebugger::handlePrintDeref(CmdQueueItem* cmd, const char* output)
1472 {
1473     ASSERT(cmd->m_expr != 0);
1474 
1475     ExprValue* variable = m_d->parsePrintExpr(output, true);
1476     if (variable == 0)
1477 	return false;
1478 
1479     // set expression "name"
1480     variable->m_name = cmd->m_expr->getText();
1481 
1482     {
1483 	/*
1484 	 * We must insert a dummy parent, because otherwise variable's value
1485 	 * would overwrite cmd->m_expr's value.
1486 	 */
1487 	ExprValue* dummyParent = new ExprValue(variable->m_name, VarTree::NKplain);
1488 	dummyParent->m_varKind = VarTree::VKdummy;
1489 	// the name of the parsed variable is the address of the pointer
1490 	QString addr = "*" + cmd->m_expr->value();
1491 	variable->m_name = addr;
1492 	variable->m_nameKind = VarTree::NKaddress;
1493 
1494 	dummyParent->m_child = variable;
1495 	// expand the first level for convenience
1496 	variable->m_initiallyExpanded = true;
1497 	TRACE("update ptr: " + cmd->m_expr->getText());
1498 	cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent, *m_typeTable);
1499 	delete dummyParent;
1500     }
1501 
1502     evalExpressions();			/* enqueue dereferenced pointers */
1503 
1504     return true;
1505 }
1506 
1507 // parse the output of bt
handleBacktrace(const char * output)1508 void KDebugger::handleBacktrace(const char* output)
1509 {
1510     m_btWindow.clear();
1511 
1512     std::list<StackFrame> stack;
1513     m_d->parseBackTrace(output, stack);
1514 
1515     if (!stack.empty()) {
1516 	std::list<StackFrame>::iterator frm = stack.begin();
1517 	// first frame must set PC
1518 	// note: frm->lineNo is zero-based
1519 	emit updatePC(frm->fileName, frm->lineNo, frm->address, frm->frameNo);
1520 
1521 	for (; frm != stack.end(); ++frm) {
1522 	    QString func;
1523 	    if (frm->var != 0)
1524 		func = frm->var->m_name;
1525 	    else
1526 		func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1527 
1528  	    m_btWindow.addItem(func);
1529 	    TRACE("frame " + func + " (" + frm->fileName + ":" +
1530 		  QString().setNum(frm->lineNo+1) + ")");
1531 	}
1532     }
1533 
1534 }
1535 
gotoFrame(int frame)1536 void KDebugger::gotoFrame(int frame)
1537 {
1538     // frame is negative when the backtrace list is cleared
1539     // ignore this event
1540     if (frame < 0)
1541 	return;
1542     m_d->executeCmd(DCframe, frame);
1543 }
1544 
handleFrameChange(const char * output)1545 void KDebugger::handleFrameChange(const char* output)
1546 {
1547     QString fileName;
1548     int frameNo;
1549     int lineNo;
1550     DbgAddr address;
1551     if (m_d->parseFrameChange(output, frameNo, fileName, lineNo, address)) {
1552 	/* lineNo can be negative here if we can't find a file name */
1553 	emit updatePC(fileName, lineNo, address, frameNo);
1554     } else {
1555 	emit updatePC(fileName, -1, address, frameNo);
1556     }
1557 }
1558 
evalExpressions()1559 void KDebugger::evalExpressions()
1560 {
1561     // evaluate expressions in the following order:
1562     //   watch expressions
1563     //   pointers in local variables
1564     //   pointers in watch expressions
1565     //   types in local variables
1566     //   types in watch expressions
1567     //   struct members in local variables
1568     //   struct members in watch expressions
1569     VarTree* exprItem = 0;
1570     if (!m_watchEvalExpr.empty())
1571     {
1572 	QString expr = m_watchEvalExpr.front();
1573 	m_watchEvalExpr.pop_front();
1574 	exprItem = m_watchVariables.topLevelExprByName(expr);
1575     }
1576     if (exprItem != 0) {
1577 	CmdQueueItem* cmd = m_d->queueCmd(DCprint, exprItem->getText());
1578 	// remember which expr this was
1579 	cmd->m_expr = exprItem;
1580 	cmd->m_exprWnd = &m_watchVariables;
1581     } else {
1582 	ExprWnd* wnd;
1583 #define POINTER(widget) \
1584 		wnd = &widget; \
1585 		exprItem = widget.nextUpdatePtr(); \
1586 		if (exprItem != 0) goto pointer
1587 #define STRUCT(widget) \
1588 		wnd = &widget; \
1589 		exprItem = widget.nextUpdateStruct(); \
1590 		if (exprItem != 0) goto ustruct
1591 #define TYPE(widget) \
1592 		wnd = &widget; \
1593 		exprItem = widget.nextUpdateType(); \
1594 		if (exprItem != 0) goto type
1595     repeat:
1596 	POINTER(m_localVariables);
1597 	POINTER(m_watchVariables);
1598 	STRUCT(m_localVariables);
1599 	STRUCT(m_watchVariables);
1600 	TYPE(m_localVariables);
1601 	TYPE(m_watchVariables);
1602 #undef POINTER
1603 #undef STRUCT
1604 #undef TYPE
1605 	return;
1606 
1607 	pointer:
1608 	// we have an expression to send
1609 	dereferencePointer(wnd, exprItem, false);
1610 	return;
1611 
1612 	ustruct:
1613 	// paranoia
1614 	if (exprItem->m_type == 0 || exprItem->m_type == TypeInfo::unknownType())
1615 	    goto repeat;
1616 	evalInitialStructExpression(exprItem, wnd, false);
1617 	return;
1618 
1619 	type:
1620 	/*
1621 	 * Sometimes a VarTree gets registered twice for a type update. So
1622 	 * it may happen that it has already been updated. Hence, we ignore
1623 	 * it here and go on to the next task.
1624 	 */
1625 	if (exprItem->m_type != 0)
1626 	    goto repeat;
1627 	determineType(wnd, exprItem);
1628     }
1629 }
1630 
dereferencePointer(ExprWnd * wnd,VarTree * exprItem,bool immediate)1631 void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem,
1632 				   bool immediate)
1633 {
1634     ASSERT(exprItem->m_varKind == VarTree::VKpointer);
1635 
1636     QString expr = exprItem->computeExpr();
1637     TRACE("dereferencing pointer: " + expr);
1638     CmdQueueItem* cmd;
1639     if (immediate) {
1640 	cmd = m_d->queueCmdPrio(DCprintDeref, expr);
1641     } else {
1642 	cmd = m_d->queueCmd(DCprintDeref, expr);
1643     }
1644     // remember which expr this was
1645     cmd->m_expr = exprItem;
1646     cmd->m_exprWnd = wnd;
1647 }
1648 
determineType(ExprWnd * wnd,VarTree * exprItem)1649 void KDebugger::determineType(ExprWnd* wnd, VarTree* exprItem)
1650 {
1651     ASSERT(exprItem->m_varKind == VarTree::VKstruct);
1652 
1653     QString expr = exprItem->computeExpr();
1654     TRACE("get type of: " + expr);
1655     CmdQueueItem* cmd;
1656     cmd = m_d->queueCmd(DCfindType, expr);
1657 
1658     // remember which expr this was
1659     cmd->m_expr = exprItem;
1660     cmd->m_exprWnd = wnd;
1661 }
1662 
handleFindType(CmdQueueItem * cmd,const char * output)1663 void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output)
1664 {
1665     QString type;
1666     if (m_d->parseFindType(output, type))
1667     {
1668 	ASSERT(cmd != 0 && cmd->m_expr != 0);
1669 
1670 	const TypeInfo* info = m_typeTable->lookup(type);
1671 
1672 	if (info == 0) {
1673 	    /*
1674 	     * We've asked gdb for the type of the expression in
1675 	     * cmd->m_expr, but it returned a name we don't know. The base
1676 	     * class (and member) types have been checked already (at the
1677 	     * time when we parsed that particular expression). Now it's
1678 	     * time to derive the type from the base classes as a last
1679 	     * resort.
1680 	     */
1681 	    info = cmd->m_expr->inferTypeFromBaseClass();
1682 	    // if we found a type through this method, register an alias
1683 	    if (info != 0) {
1684 		TRACE("infered alias: " + type);
1685 		m_typeTable->registerAlias(type, info);
1686 	    }
1687 	}
1688 	if (info == 0) {
1689             TRACE("unknown type "+type);
1690 	    cmd->m_expr->m_type = TypeInfo::unknownType();
1691 	} else {
1692 	    cmd->m_expr->m_type = info;
1693 	    /* since this node has a new type, we get its value immediately */
1694 	    evalInitialStructExpression(cmd->m_expr, cmd->m_exprWnd, false);
1695 	    return;
1696 	}
1697     }
1698 
1699     evalExpressions();			/* queue more of them */
1700 }
1701 
handlePrintStruct(CmdQueueItem * cmd,const char * output)1702 void KDebugger::handlePrintStruct(CmdQueueItem* cmd, const char* output)
1703 {
1704     VarTree* var = cmd->m_expr;
1705     ASSERT(var != 0);
1706     ASSERT(var->m_varKind == VarTree::VKstruct);
1707 
1708     ExprValue* partExpr;
1709     if (cmd->m_cmd == DCprintQStringStruct) {
1710 	partExpr = m_d->parseQCharArray(output, false, m_typeTable->qCharIsShort());
1711     } else if (cmd->m_cmd == DCprintWChar) {
1712 	partExpr = m_d->parseQCharArray(output, false, true);
1713     } else {
1714 	partExpr = m_d->parsePrintExpr(output, false);
1715     }
1716     bool errorValue =
1717 	partExpr == 0 ||
1718 	/* we only allow simple values at the moment */
1719 	partExpr->m_child != 0;
1720 
1721     QString partValue;
1722     if (errorValue)
1723     {
1724 	partValue = "?""?""?";	// 2 question marks in a row would be a trigraph
1725     } else {
1726 	partValue = partExpr->m_value;
1727     }
1728     delete partExpr;
1729     partExpr = 0;
1730 
1731     /*
1732      * Updating a struct value works like this: var->m_partialValue holds
1733      * the value that we have gathered so far (it's been initialized with
1734      * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1735      * we append the printed result followed by the next
1736      * var->m_type->m_displayString to var->m_partialValue.
1737      *
1738      * If the expression we just evaluated was a guard expression, and it
1739      * resulted in an error, we must not evaluate the real expression, but
1740      * go on to the next index. (We must still add the question marks to
1741      * the value).
1742      *
1743      * Next, if this was the length expression, we still have not seen the
1744      * real expression, but the length of a QString.
1745      */
1746     ASSERT(var->m_exprIndex >= 0 && var->m_exprIndex <= typeInfoMaxExpr);
1747 
1748     if (errorValue || !var->m_exprIndexUseGuard)
1749     {
1750 	// add current partValue (which might be the question marks)
1751 	var->m_partialValue += partValue;
1752 	var->m_exprIndex++;		/* next part */
1753 	var->m_exprIndexUseGuard = true;
1754 	var->m_partialValue += var->m_type->m_displayString[var->m_exprIndex];
1755     }
1756     else
1757     {
1758 	// this was a guard expression that succeeded
1759 	// go for the real expression
1760 	var->m_exprIndexUseGuard = false;
1761     }
1762 
1763     /* go for more sub-expressions if needed */
1764     if (var->m_exprIndex < var->m_type->m_numExprs) {
1765 	/* queue a new print command with quite high priority */
1766 	evalStructExpression(var, cmd->m_exprWnd, true);
1767 	return;
1768     }
1769 
1770     cmd->m_exprWnd->updateStructValue(var);
1771 
1772     evalExpressions();			/* enqueue dereferenced pointers */
1773 }
1774 
1775 /* queues the first printStruct command for a struct */
evalInitialStructExpression(VarTree * var,ExprWnd * wnd,bool immediate)1776 void KDebugger::evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1777 {
1778     var->m_exprIndex = 0;
1779     if (var->m_type != TypeInfo::wchartType())
1780     {
1781 	var->m_exprIndexUseGuard = true;
1782 	var->m_partialValue = var->m_type->m_displayString[0];
1783 	evalStructExpression(var, wnd, immediate);
1784     }
1785     else
1786     {
1787 	var->m_exprIndexUseGuard = false;
1788 	QString expr = var->computeExpr();
1789 	CmdQueueItem* cmd = immediate  ?
1790 				m_d->queueCmdPrio(DCprintWChar, expr)  :
1791 				m_d->queueCmd(DCprintWChar, expr)  ;
1792 	// remember which expression this was
1793 	cmd->m_expr = var;
1794 	cmd->m_exprWnd = wnd;
1795     }
1796 }
1797 
1798 /** queues a printStruct command; var must have been initialized correctly */
evalStructExpression(VarTree * var,ExprWnd * wnd,bool immediate)1799 void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1800 {
1801     QString base = var->computeExpr();
1802     QString expr;
1803     if (var->m_exprIndexUseGuard) {
1804 	expr = var->m_type->m_guardStrings[var->m_exprIndex];
1805 	if (expr.isEmpty()) {
1806 	    // no guard, omit it and go to expression
1807 	    var->m_exprIndexUseGuard = false;
1808 	}
1809     }
1810     if (!var->m_exprIndexUseGuard) {
1811 	expr = var->m_type->m_exprStrings[var->m_exprIndex];
1812     }
1813 
1814     expr.replace("%s", base);
1815 
1816     DbgCommand dbgCmd = DCprintStruct;
1817     // check if this is a QString::Data
1818     if (expr.left(15) == "/QString::Data ")
1819     {
1820 	if (m_typeTable->parseQt2QStrings())
1821 	{
1822 	    expr = expr.mid(15, expr.length());	/* strip off /QString::Data */
1823 	    dbgCmd = DCprintQStringStruct;
1824 	} else {
1825 	    /*
1826 	     * This should not happen: the type libraries should be set up
1827 	     * in a way that this can't happen. If this happens
1828 	     * nevertheless it means that, eg., kdecore was loaded but qt2
1829 	     * was not (only qt2 enables the QString feature).
1830 	     */
1831 	    // TODO: remove this "print"; queue the next printStruct instead
1832 	    expr = "*0";
1833 	}
1834     }
1835     TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1836     CmdQueueItem* cmd = immediate  ?
1837 			m_d->queueCmdPrio(dbgCmd, expr)  :
1838 			m_d->queueCmd(dbgCmd, expr);
1839 
1840     // remember which expression this was
1841     cmd->m_expr = var;
1842     cmd->m_exprWnd = wnd;
1843 }
1844 
handleSharedLibs(const char * output)1845 void KDebugger::handleSharedLibs(const char* output)
1846 {
1847     // parse the table of shared libraries
1848     m_sharedLibs = m_d->parseSharedLibs(output);
1849     m_sharedLibsListed = true;
1850 
1851     // get type libraries
1852     m_typeTable->loadLibTypes(m_sharedLibs);
1853 
1854     // hand over the QString data cmd
1855     m_d->setPrintQStringDataCmd(m_typeTable->printQStringDataCmd());
1856 }
1857 
loadCoreFile()1858 CmdQueueItem* KDebugger::loadCoreFile()
1859 {
1860     return m_d->queueCmd(DCcorefile, m_corefile);
1861 }
1862 
slotExpanding(QTreeWidgetItem * item)1863 void KDebugger::slotExpanding(QTreeWidgetItem* item)
1864 {
1865     VarTree* exprItem = static_cast<VarTree*>(item);
1866     if (exprItem->m_varKind != VarTree::VKpointer) {
1867 	return;
1868     }
1869     ExprWnd* wnd = static_cast<ExprWnd*>(item->treeWidget());
1870     dereferencePointer(wnd, exprItem, true);
1871 }
1872 
1873 // add the expression in the edit field to the watch expressions
addWatch(const QString & t)1874 void KDebugger::addWatch(const QString& t)
1875 {
1876     QString expr = t.trimmed();
1877     // don't add a watched expression again
1878     if (expr.isEmpty() || m_watchVariables.topLevelExprByName(expr) != 0)
1879 	return;
1880     ExprValue e(expr, VarTree::NKplain);
1881     m_watchVariables.insertExpr(&e, *m_typeTable);
1882 
1883     // if we are boring ourselves, send down the command
1884     if (m_programActive) {
1885 	m_watchEvalExpr.push_back(expr);
1886 	if (m_d->isIdle()) {
1887 	    evalExpressions();
1888 	}
1889     }
1890 }
1891 
1892 // delete a toplevel watch expression
slotDeleteWatch()1893 void KDebugger::slotDeleteWatch()
1894 {
1895     // delete only allowed while debugger is idle; or else we might delete
1896     // the very expression the debugger is currently working on...
1897     if (m_d == 0 || !m_d->isIdle())
1898 	return;
1899 
1900     VarTree* item = m_watchVariables.selectedItem();
1901     if (item == 0 || !item->isToplevelExpr())
1902 	return;
1903 
1904     // remove the variable from the list to evaluate
1905     std::list<QString>::iterator i =
1906 	    std::find(m_watchEvalExpr.begin(), m_watchEvalExpr.end(), item->getText());
1907     if (i != m_watchEvalExpr.end()) {
1908 	m_watchEvalExpr.erase(i);
1909     }
1910     m_watchVariables.removeExpr(item);
1911     // item is invalid at this point!
1912 }
1913 
handleRegisters(const char * output)1914 void KDebugger::handleRegisters(const char* output)
1915 {
1916     emit registersChanged(m_d->parseRegisters(output));
1917 }
1918 
1919 /*
1920  * The output of the DCbreak* commands has more accurate information about
1921  * the file and the line number.
1922  *
1923  * All newly set breakpoints are inserted in the m_brkpts, even those that
1924  * were not set sucessfully. The unsuccessful breakpoints ("orphaned
1925  * breakpoints") are assigned negative ids, and they are tried to set later
1926  * when the program stops again at a breakpoint.
1927  */
newBreakpoint(CmdQueueItem * cmd,const char * output)1928 void KDebugger::newBreakpoint(CmdQueueItem* cmd, const char* output)
1929 {
1930     BrkptIterator bp;
1931     if (cmd->m_brkpt != 0) {
1932 	// a new breakpoint, put it in the list
1933 	assert(cmd->m_brkpt->id == 0);
1934 	m_brkpts.push_back(*cmd->m_brkpt);
1935 	delete cmd->m_brkpt;
1936 	bp = m_brkpts.end();
1937 	--bp;
1938     } else {
1939 	// an existing breakpoint was retried
1940 	assert(cmd->m_existingBrkpt != 0);
1941 	bp = breakpointById(cmd->m_existingBrkpt);
1942 	if (bp == m_brkpts.end())
1943 	    return;
1944     }
1945 
1946     // parse the output to determine success or failure
1947     int id;
1948     QString file;
1949     int lineNo;
1950     QString address;
1951     if (!m_d->parseBreakpoint(output, id, file, lineNo, address))
1952     {
1953 	/*
1954 	 * Failure, the breakpoint could not be set. If this is a new
1955 	 * breakpoint, assign it a negative id. We look for the minimal id
1956 	 * of all breakpoints (that are already in the list) to get the new
1957 	 * id.
1958 	 */
1959 	if (bp->id == 0)
1960 	{
1961 	    int minId = 0;
1962 	    for (BrkptIterator i = m_brkpts.begin(); i != m_brkpts.end(); ++i) {
1963 		if (i->id < minId)
1964 		    minId = i->id;
1965 	    }
1966 	    bp->id = minId-1;
1967 	}
1968 	return;
1969     }
1970 
1971     // The breakpoint was successfully set.
1972     if (bp->id <= 0)
1973     {
1974 	// this is a new or orphaned breakpoint:
1975 	// set the remaining properties
1976 	if (!bp->enabled) {
1977 	    m_d->executeCmd(DCdisable, id);
1978 	}
1979 	if (!bp->condition.isEmpty()) {
1980 	    m_d->executeCmd(DCcondition, bp->condition, id);
1981 	}
1982     }
1983 
1984     bp->id = id;
1985     bp->fileName = file;
1986     bp->lineNo = lineNo;
1987     if (!address.isEmpty())
1988 	bp->address = address;
1989 }
1990 
updateBreakList(const char * output)1991 void KDebugger::updateBreakList(const char* output)
1992 {
1993     // get the new list
1994     std::list<Breakpoint> brks;
1995     m_d->parseBreakList(output, brks);
1996 
1997     // merge existing information into the new list
1998     // then swap the old and new lists
1999 
2000     for (BrkptIterator bp = brks.begin(); bp != brks.end(); ++bp)
2001     {
2002 	BrkptIterator i = breakpointById(bp->id);
2003 	if (i != m_brkpts.end())
2004 	{
2005 	    // preserve accurate location information
2006 	    // note that xsldbg doesn't have a location in
2007 	    // the listed breakpoint if it has just been set
2008 	    // therefore, we copy it as well if necessary
2009 	    bp->text = i->text;
2010 	    if (!i->fileName.isEmpty()) {
2011 		bp->fileName = i->fileName;
2012 		bp->lineNo = i->lineNo;
2013 	    }
2014 	}
2015     }
2016 
2017     // orphaned breakpoints must be copied
2018     for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
2019     {
2020 	if (bp->isOrphaned())
2021 	    brks.push_back(*bp);
2022     }
2023 
2024     m_brkpts.swap(brks);
2025     emit breakpointsChanged();
2026 }
2027 
2028 // look if there is at least one temporary breakpoint
2029 // or a watchpoint
stopMayChangeBreakList() const2030 bool KDebugger::stopMayChangeBreakList() const
2031 {
2032     for (BrkptROIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
2033     {
2034 	if (bp->temporary || bp->type == Breakpoint::watchpoint)
2035 	    return true;
2036     }
2037     return false;
2038 }
2039 
breakpointByFilePos(QString file,int lineNo,const DbgAddr & address)2040 KDebugger::BrkptIterator KDebugger::breakpointByFilePos(QString file, int lineNo,
2041 					   const DbgAddr& address)
2042 {
2043     // look for exact file name match
2044     for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
2045     {
2046 	if (bp->lineNo == lineNo &&
2047 	    bp->fileName == file &&
2048 	    (address.isEmpty() || bp->address == address))
2049 	{
2050 	    return bp;
2051 	}
2052     }
2053     // not found, so try basename
2054     file = QFileInfo(file).fileName();
2055 
2056     for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
2057     {
2058 	// get base name of breakpoint's file
2059 	QString basename = QFileInfo(bp->fileName).fileName();
2060 
2061 	if (bp->lineNo == lineNo &&
2062 	    basename == file &&
2063 	    (address.isEmpty() || bp->address == address))
2064 	{
2065 	    return bp;
2066 	}
2067     }
2068 
2069     // not found
2070     return m_brkpts.end();
2071 }
2072 
breakpointById(int id)2073 KDebugger::BrkptIterator KDebugger::breakpointById(int id)
2074 {
2075     for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
2076     {
2077 	if (bp->id == id) {
2078 	    return bp;
2079 	}
2080     }
2081     // not found
2082     return m_brkpts.end();
2083 }
2084 
slotValuePopup(const QString & expr)2085 void KDebugger::slotValuePopup(const QString& expr)
2086 {
2087     // search the local variables for a match
2088     VarTree* v = m_localVariables.topLevelExprByName(expr);
2089     if (v == 0) {
2090 	// not found, check watch expressions
2091 	v = m_watchVariables.topLevelExprByName(expr);
2092 	if (v == 0) {
2093 	    // try a member of 'this'
2094 	    v = m_localVariables.topLevelExprByName("this");
2095 	    if (v != 0)
2096 		v = ExprWnd::ptrMemberByName(v, expr);
2097 	    if (v == 0) {
2098 		// nothing found, try printing variable in gdb
2099 		if (m_d) {
2100 		    CmdQueueItem *cmd = m_d->executeCmd(DCprintPopup, expr);
2101 		    cmd->m_popupExpr = expr;
2102 		}
2103 		return;
2104 	    }
2105 	}
2106     }
2107 
2108     // construct the tip
2109     QString tip = v->getText() + " = " + formatPopupValue(v);
2110     emit valuePopup(tip);
2111 }
2112 
slotDisassemble(const QString & fileName,int lineNo)2113 void KDebugger::slotDisassemble(const QString& fileName, int lineNo)
2114 {
2115     if (m_haveExecutable) {
2116 	CmdQueueItem* cmd = m_d->queueCmdPrio(DCinfoline, fileName, lineNo);
2117 	cmd->m_fileName = fileName;
2118 	cmd->m_lineNo = lineNo;
2119     }
2120 }
2121 
handleInfoLine(CmdQueueItem * cmd,const char * output)2122 void KDebugger::handleInfoLine(CmdQueueItem* cmd, const char* output)
2123 {
2124     QString addrFrom, addrTo;
2125     if (cmd->m_lineNo >= 0) {
2126 	// disassemble
2127 	if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2128 	    // got the address range, now get the real code
2129 	    CmdQueueItem* c = m_d->queueCmdPrio(DCdisassemble, addrFrom, addrTo);
2130 	    c->m_fileName = cmd->m_fileName;
2131 	    c->m_lineNo = cmd->m_lineNo;
2132 	} else {
2133 	    // no code
2134 	    emit disassembled(cmd->m_fileName, cmd->m_lineNo, std::list<DisassembledCode>());
2135 	}
2136     } else {
2137 	// set program counter
2138 	if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2139 	    // move the program counter to the start address
2140 	    m_d->executeCmd(DCsetpc, addrFrom);
2141 	}
2142     }
2143 }
2144 
handleDisassemble(CmdQueueItem * cmd,const char * output)2145 void KDebugger::handleDisassemble(CmdQueueItem* cmd, const char* output)
2146 {
2147     emit disassembled(cmd->m_fileName, cmd->m_lineNo,
2148 		      m_d->parseDisassemble(output));
2149 }
2150 
handleThreadList(const char * output)2151 void KDebugger::handleThreadList(const char* output)
2152 {
2153     emit threadsChanged(m_d->parseThreadList(output));
2154 }
2155 
setThread(int id)2156 void KDebugger::setThread(int id)
2157 {
2158     m_d->queueCmdPrio(DCthread, id);
2159 }
2160 
setMemoryExpression(const QString & start_memexpr,unsigned total_length,const QString & current_memexpr,unsigned current_length)2161 void KDebugger::setMemoryExpression(const QString& start_memexpr, unsigned total_length,
2162         const QString& current_memexpr, unsigned current_length)
2163 {
2164     m_memoryExpression = current_memexpr;
2165     m_memoryLength = current_length;
2166     m_memoryStartExpression = start_memexpr;
2167     m_memoryTotalLength = total_length;
2168 
2169     // queue the new expression
2170     if (!m_memoryExpression.isEmpty() &&
2171 	isProgramActive() &&
2172 	!isProgramRunning())
2173     {
2174 	queueMemoryDump(true, false);
2175     }
2176 }
2177 
queueMemoryDump(bool immediate,bool update)2178 void KDebugger::queueMemoryDump(bool immediate, bool update)
2179 {
2180     if (update) {
2181 	if (immediate)
2182 	    m_d->queueCmdPrio(DCexamine, m_memoryStartExpression, m_memoryFormat, m_memoryTotalLength);
2183 	else
2184 	    m_d->queueCmd(DCexamine, m_memoryStartExpression, m_memoryFormat, m_memoryTotalLength);
2185     } else {
2186 	if (immediate)
2187 	    m_d->queueCmdPrio(DCexamine, m_memoryExpression, m_memoryFormat, m_memoryLength);
2188 	else
2189 	    m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat, m_memoryLength);
2190     }
2191 }
2192 
handleMemoryDump(const char * output)2193 void KDebugger::handleMemoryDump(const char* output)
2194 {
2195     std::list<MemoryDump> memdump;
2196     QString msg = m_d->parseMemoryDump(output, memdump);
2197     emit memoryDumpChanged(msg, memdump);
2198 }
2199 
setProgramCounter(const QString & file,int line,const DbgAddr & addr)2200 void KDebugger::setProgramCounter(const QString& file, int line, const DbgAddr& addr)
2201 {
2202     if (addr.isEmpty()) {
2203 	// find address of the specified line
2204 	CmdQueueItem* cmd = m_d->executeCmd(DCinfoline, file, line);
2205 	cmd->m_lineNo = -1;		/* indicates "Set PC" UI command */
2206     } else {
2207 	// move the program counter to that address
2208 	m_d->executeCmd(DCsetpc, addr.asString());
2209     }
2210 }
2211 
handleSetPC(const char *)2212 void KDebugger::handleSetPC(const char* /*output*/)
2213 {
2214     // TODO: handle errors
2215 
2216     // now go to the top-most frame
2217     // this also modifies the program counter indicator in the UI
2218     gotoFrame(0);
2219 }
2220 
slotValueEdited(VarTree * expr,const QString & text)2221 void KDebugger::slotValueEdited(VarTree* expr, const QString& text)
2222 {
2223     if (text.simplified().isEmpty())
2224 	return;			       /* no text entered: ignore request */
2225 
2226     ExprWnd* wnd = static_cast<ExprWnd*>(expr->treeWidget());
2227     TRACE(QString().sprintf("Changing %s to ",
2228 			    wnd->name()) + text);
2229 
2230     // determine the lvalue to edit
2231     QString lvalue = expr->computeExpr();
2232     CmdQueueItem* cmd = m_d->executeCmd(DCsetvariable, lvalue, text);
2233     cmd->m_expr = expr;
2234     cmd->m_exprWnd = wnd;
2235 }
2236 
handleSetVariable(CmdQueueItem * cmd,const char * output)2237 void KDebugger::handleSetVariable(CmdQueueItem* cmd, const char* output)
2238 {
2239     QString msg = m_d->parseSetVariable(output);
2240     if (!msg.isEmpty())
2241     {
2242 	// there was an error; display it in the status bar
2243 	m_statusMessage = msg;
2244 	emit updateStatusMessage();
2245 	return;
2246     }
2247 
2248     // get the new value
2249     QString expr = cmd->m_expr->computeExpr();
2250     CmdQueueItem* printCmd = m_d->queueCmdPrio(DCprint, expr);
2251     printCmd->m_expr = cmd->m_expr;
2252     printCmd->m_exprWnd = cmd->m_exprWnd;
2253 }
2254 
2255 
2256 #include "debugger.moc"
2257