xsldbg can set more that one breakpoint in one command: put them in the list.
[kdbg.git] / kdbg / debugger.cpp
blobdea86f05dd1e11dddafc222a78382868a07ed6f4
1 // $Id$
3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include "debugger.h"
7 #include "dbgdriver.h"
8 #include "pgmargs.h"
9 #include "typetable.h"
10 #include "exprwnd.h"
11 #include "pgmsettings.h"
12 #include "valarray.h"
13 #include <qregexp.h>
14 #include <qfileinfo.h>
15 #include <qlistbox.h>
16 #include <qstringlist.h>
17 #include <kapp.h>
18 #include <ksimpleconfig.h>
19 #include <kconfig.h>
20 #include <klocale.h> /* i18n */
21 #include <kmessagebox.h>
22 #include <ctype.h>
23 #include <stdlib.h> /* strtol, atoi */
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h> /* sleep(3) */
26 #endif
27 #include "mydebug.h"
30 KDebugger::KDebugger(QWidget* parent,
31 ExprWnd* localVars,
32 ExprWnd* watchVars,
33 QListBox* backtrace) :
34 QObject(parent, "debugger"),
35 m_ttyLevel(ttyFull),
36 m_memoryFormat(MDTword | MDThex),
37 m_haveExecutable(false),
38 m_programActive(false),
39 m_programRunning(false),
40 m_sharedLibsListed(false),
41 m_typeTable(0),
42 m_programConfig(0),
43 m_d(0),
44 m_localVariables(*localVars),
45 m_watchVariables(*watchVars),
46 m_btWindow(*backtrace),
47 m_animationTimer(this),
48 m_animationInterval(0)
50 m_envVars.setAutoDelete(true);
51 m_brkpts.setAutoDelete(true);
53 connect(&m_localVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
54 SLOT(slotLocalsExpanding(KTreeViewItem*,bool&)));
55 connect(&m_watchVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
56 SLOT(slotWatchExpanding(KTreeViewItem*,bool&)));
58 connect(&m_btWindow, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
60 // animation
61 connect(&m_animationTimer, SIGNAL(timeout()), SIGNAL(animationTimeout()));
62 // special update of animation
63 connect(this, SIGNAL(updateUI()), SLOT(slotUpdateAnimation()));
65 emit updateUI();
68 KDebugger::~KDebugger()
70 if (m_programConfig != 0) {
71 saveProgramSettings();
72 m_programConfig->sync();
73 delete m_programConfig;
76 delete m_typeTable;
80 void KDebugger::saveSettings(KConfig* /*config*/)
84 void KDebugger::restoreSettings(KConfig* /*config*/)
89 //////////////////////////////////////////////////////////////////////
90 // external interface
92 const char GeneralGroup[] = "General";
93 const char DebuggerCmdStr[] = "DebuggerCmdStr";
94 const char TTYLevelEntry[] = "TTYLevel";
95 const char KDebugger::DriverNameEntry[] = "DriverName";
97 bool KDebugger::debugProgram(const QString& name,
98 DebuggerDriver* driver)
100 if (m_d != 0 && m_d->isRunning())
102 QApplication::setOverrideCursor(waitCursor);
104 stopDriver();
106 QApplication::restoreOverrideCursor();
108 if (m_d->isRunning() || m_haveExecutable) {
109 /* timed out! We can't really do anything useful now */
110 TRACE("timed out while waiting for gdb to die!");
111 return false;
113 delete m_d;
114 m_d = 0;
117 // wire up the driver
118 connect(driver, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
119 this, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)));
120 connect(driver, SIGNAL(processExited(KProcess*)), SLOT(gdbExited(KProcess*)));
121 connect(driver, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
122 SLOT(parse(CmdQueueItem*,const char*)));
123 connect(driver, SIGNAL(wroteStdin(KProcess*)), SIGNAL(updateUI()));
124 connect(driver, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
125 connect(driver, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
126 connect(driver, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
128 // create the program settings object
129 openProgramConfig(name);
131 // get debugger command from per-program settings
132 if (m_programConfig != 0) {
133 m_programConfig->setGroup(GeneralGroup);
134 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
135 // get terminal emulation level
136 m_ttyLevel = TTYLevel(m_programConfig->readNumEntry(TTYLevelEntry, ttyFull));
138 // the rest is read in later in the handler of DCexecutable
140 m_d = driver;
142 if (!startDriver()) {
143 TRACE("startDriver failed");
144 m_d = 0;
145 return false;
148 TRACE("before file cmd");
149 m_d->executeCmd(DCexecutable, name);
150 m_executable = name;
152 // set remote target
153 if (!m_remoteDevice.isEmpty()) {
154 m_d->executeCmd(DCtargetremote, m_remoteDevice);
155 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
156 m_d->queueCmd(DCframe, 0, DebuggerDriver::QMnormal);
157 m_programActive = true;
158 m_haveExecutable = true;
161 // create a type table
162 m_typeTable = new ProgramTypeTable;
163 m_sharedLibsListed = false;
165 emit updateUI();
167 return true;
170 void KDebugger::shutdown()
172 // shut down debugger driver
173 if (m_d != 0 && m_d->isRunning())
175 stopDriver();
179 void KDebugger::useCoreFile(QString corefile, bool batch)
181 m_corefile = corefile;
182 if (!batch) {
183 CmdQueueItem* cmd = loadCoreFile();
184 cmd->m_byUser = true;
188 void KDebugger::programRun()
190 if (!isReady())
191 return;
193 // when program is active, but not a core file, continue
194 // otherwise run the program
195 if (m_programActive && m_corefile.isEmpty()) {
196 // gdb command: continue
197 m_d->executeCmd(DCcont, true);
198 } else {
199 // gdb command: run
200 m_d->executeCmd(DCrun, true);
201 m_corefile = QString();
202 m_programActive = true;
204 m_programRunning = true;
207 void KDebugger::attachProgram(const QString& pid)
209 if (!isReady())
210 return;
212 m_attachedPid = pid;
213 TRACE("Attaching to " + m_attachedPid);
214 m_d->executeCmd(DCattach, m_attachedPid);
215 m_programActive = true;
216 m_programRunning = true;
219 void KDebugger::programRunAgain()
221 if (canSingleStep()) {
222 m_d->executeCmd(DCrun, true);
223 m_corefile = QString();
224 m_programRunning = true;
228 void KDebugger::programStep()
230 if (canSingleStep()) {
231 m_d->executeCmd(DCstep, true);
232 m_programRunning = true;
236 void KDebugger::programNext()
238 if (canSingleStep()) {
239 m_d->executeCmd(DCnext, true);
240 m_programRunning = true;
244 void KDebugger::programStepi()
246 if (canSingleStep()) {
247 m_d->executeCmd(DCstepi, true);
248 m_programRunning = true;
252 void KDebugger::programNexti()
254 if (canSingleStep()) {
255 m_d->executeCmd(DCnexti, true);
256 m_programRunning = true;
260 void KDebugger::programFinish()
262 if (canSingleStep()) {
263 m_d->executeCmd(DCfinish, true);
264 m_programRunning = true;
268 void KDebugger::programKill()
270 if (haveExecutable() && isProgramActive()) {
271 if (m_programRunning) {
272 m_d->interruptInferior();
274 // this is an emergency command; flush queues
275 m_d->flushCommands(true);
276 m_d->executeCmd(DCkill, true);
280 bool KDebugger::runUntil(const QString& fileName, int lineNo)
282 if (isReady() && m_programActive && !m_programRunning) {
283 // strip off directory part of file name
284 QString file = fileName;
285 int offset = file.findRev("/");
286 if (offset >= 0) {
287 file.remove(0, offset+1);
289 m_d->executeCmd(DCuntil, file, lineNo, true);
290 m_programRunning = true;
291 return true;
292 } else {
293 return false;
297 void KDebugger::programBreak()
299 if (m_haveExecutable && m_programRunning) {
300 m_d->interruptInferior();
304 void KDebugger::programArgs(QWidget* parent)
306 if (m_haveExecutable) {
307 QStringList allOptions = m_d->boolOptionList();
308 PgmArgs dlg(parent, m_executable, m_envVars, allOptions);
309 dlg.setArgs(m_programArgs);
310 dlg.setWd(m_programWD);
311 dlg.setOptions(m_boolOptions);
312 if (dlg.exec()) {
313 updateProgEnvironment(dlg.args(), dlg.wd(),
314 dlg.envVars(), dlg.options());
319 void KDebugger::programSettings(QWidget* parent)
321 if (!m_haveExecutable)
322 return;
324 ProgramSettings dlg(parent, m_executable);
326 dlg.m_chooseDriver.setDebuggerCmd(m_debuggerCmd);
327 dlg.m_output.setTTYLevel(m_ttyLevel);
329 if (dlg.exec() == QDialog::Accepted)
331 m_debuggerCmd = dlg.m_chooseDriver.debuggerCmd();
332 m_ttyLevel = TTYLevel(dlg.m_output.ttyLevel());
336 bool KDebugger::setBreakpoint(QString file, int lineNo,
337 const DbgAddr& address, bool temporary)
339 if (!isReady()) {
340 return false;
343 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
344 if (bp == 0)
347 * No such breakpoint, so set a new one. If we have an address, we
348 * set the breakpoint exactly there. Otherwise we use the file name
349 * plus line no.
351 Breakpoint* bp = new Breakpoint;
352 bp->temporary = temporary;
354 if (address.isEmpty())
356 bp->fileName = file;
357 bp->lineNo = lineNo;
359 else
361 bp->address = address;
363 setBreakpoint(bp, false);
365 else
368 * If the breakpoint is disabled, enable it; if it's enabled,
369 * delete that breakpoint.
371 if (bp->enabled) {
372 deleteBreakpoint(bp);
373 } else {
374 enableDisableBreakpoint(bp);
377 return true;
380 void KDebugger::setBreakpoint(Breakpoint* bp, bool queueOnly)
382 CmdQueueItem* cmd;
383 if (!bp->text.isEmpty())
386 * The breakpoint was set using the text box in the breakpoint
387 * list. This is the only way in which watchpoints are set.
389 if (bp->type == Breakpoint::watchpoint) {
390 cmd = m_d->executeCmd(DCwatchpoint, bp->text);
391 } else {
392 cmd = m_d->executeCmd(DCbreaktext, bp->text);
395 else if (bp->address.isEmpty())
397 // strip off directory part of file name
398 QString file = bp->fileName;
399 int offset = file.findRev("/");
400 if (offset >= 0) {
401 file.remove(0, offset+1);
403 if (queueOnly) {
404 cmd = m_d->queueCmd(bp->temporary ? DCtbreakline : DCbreakline,
405 file, bp->lineNo, DebuggerDriver::QMoverride);
406 } else {
407 cmd = m_d->executeCmd(bp->temporary ? DCtbreakline : DCbreakline,
408 file, bp->lineNo);
411 else
413 if (queueOnly) {
414 cmd = m_d->queueCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
415 bp->address.asString(), DebuggerDriver::QMoverride);
416 } else {
417 cmd = m_d->executeCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
418 bp->address.asString());
421 cmd->m_brkpt = bp; // used in newBreakpoint()
424 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo,
425 const DbgAddr& address)
427 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
428 return bp == 0 || enableDisableBreakpoint(bp);
431 bool KDebugger::enableDisableBreakpoint(Breakpoint* bp)
434 * Toggle enabled/disabled state.
436 * The driver is not bothered if we are modifying an orphaned
437 * breakpoint.
439 if (!bp->isOrphaned()) {
440 if (!canChangeBreakpoints()) {
441 return false;
443 m_d->executeCmd(bp->enabled ? DCdisable : DCenable, bp->id);
444 } else {
445 bp->enabled = !bp->enabled;
446 emit breakpointsChanged();
448 return true;
451 bool KDebugger::conditionalBreakpoint(Breakpoint* bp,
452 const QString& condition,
453 int ignoreCount)
456 * Change the condition and ignore count.
458 * The driver is not bothered if we are removing an orphaned
459 * breakpoint.
462 if (!bp->isOrphaned()) {
463 if (!canChangeBreakpoints()) {
464 return false;
467 bool changed = false;
469 if (bp->condition != condition) {
470 // change condition
471 m_d->executeCmd(DCcondition, condition, bp->id);
472 changed = true;
474 if (bp->ignoreCount != ignoreCount) {
475 // change ignore count
476 m_d->executeCmd(DCignore, bp->id, ignoreCount);
477 changed = true;
479 if (changed) {
480 // get the changes
481 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
483 } else {
484 bp->condition = condition;
485 bp->ignoreCount = ignoreCount;
486 emit breakpointsChanged();
488 return true;
491 bool KDebugger::deleteBreakpoint(Breakpoint* bp)
494 * Remove the breakpoint.
496 * The driver is not bothered if we are removing an orphaned
497 * breakpoint.
499 if (!bp->isOrphaned()) {
500 if (!canChangeBreakpoints()) {
501 return false;
503 m_d->executeCmd(DCdelete, bp->id);
504 } else {
505 // move the last entry to bp's slot and shorten the list
506 int i = m_brkpts.findRef(bp);
507 m_brkpts.insert(i, m_brkpts.take(m_brkpts.size()-1));
508 m_brkpts.resize(m_brkpts.size()-1);
509 emit breakpointsChanged();
511 return false;
514 bool KDebugger::canSingleStep()
516 return isReady() && m_programActive && !m_programRunning;
519 bool KDebugger::canChangeBreakpoints()
521 return isReady() && !m_programRunning;
524 bool KDebugger::isReady() const
526 return m_haveExecutable &&
527 m_d != 0 && m_d->canExecuteImmediately();
530 bool KDebugger::isIdle() const
532 return m_d == 0 || m_d->isIdle();
536 //////////////////////////////////////////////////////////
537 // debugger driver
539 bool KDebugger::startDriver()
541 emit debuggerStarting(); /* must set m_inferiorTerminal */
544 * If the per-program command string is empty, use the global setting
545 * (which might also be empty, in which case the driver uses its
546 * default).
548 m_explicitKill = false;
549 if (!m_d->startup(m_debuggerCmd)) {
550 return false;
554 * If we have an output terminal, we use it. Otherwise we will run the
555 * program with input and output redirected to /dev/null. Other
556 * redirections are also necessary depending on the tty emulation
557 * level.
559 int redirect = RDNstdin|RDNstdout|RDNstderr; /* redirect everything */
560 if (!m_inferiorTerminal.isEmpty()) {
561 switch (m_ttyLevel) {
562 default:
563 case ttyNone:
564 // redirect everything
565 break;
566 case ttySimpleOutputOnly:
567 redirect = RDNstdin;
568 break;
569 case ttyFull:
570 redirect = 0;
571 break;
574 m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
576 return true;
579 void KDebugger::stopDriver()
581 m_explicitKill = true;
583 if (m_attachedPid.isEmpty()) {
584 m_d->terminate();
585 } else {
586 m_d->detachAndTerminate();
590 * We MUST wait until the slot gdbExited() has been called. But to
591 * avoid a deadlock, we wait only for some certain maximum time. Should
592 * this timeout be reached, the only reasonable thing one could do then
593 * is exiting kdbg.
595 kapp->processEvents(1000); /* ideally, this will already shut it down */
596 int maxTime = 20; /* about 20 seconds */
597 while (m_haveExecutable && maxTime > 0) {
598 // give gdb time to die (and send a SIGCLD)
599 ::sleep(1);
600 --maxTime;
601 kapp->processEvents(1000);
605 void KDebugger::gdbExited(KProcess*)
608 * Save settings, but only if gdb has already processed "info line
609 * main", otherwise we would save an empty config file, because it
610 * isn't read in until then!
612 if (m_programConfig != 0) {
613 if (m_haveExecutable) {
614 saveProgramSettings();
615 m_programConfig->sync();
617 delete m_programConfig;
618 m_programConfig = 0;
621 // erase types
622 delete m_typeTable;
623 m_typeTable = 0;
625 if (m_explicitKill) {
626 TRACE(m_d->driverName() + " exited normally");
627 } else {
628 QString msg = i18n("%1 exited unexpectedly.\n"
629 "Restart the session (e.g. with File|Executable).");
630 KMessageBox::error(parentWidget(), msg.arg(m_d->driverName()));
633 // reset state
634 m_haveExecutable = false;
635 m_executable = "";
636 m_programActive = false;
637 m_programRunning = false;
638 m_explicitKill = false;
639 m_debuggerCmd = QString(); /* use global setting at next start! */
640 m_attachedPid = QString(); /* we are no longer attached to a process */
641 m_ttyLevel = ttyFull;
642 m_brkpts.clear();
644 // stop gear wheel and erase PC
645 stopAnimation();
646 emit updatePC(QString(), -1, DbgAddr(), 0);
649 QString KDebugger::getConfigForExe(const QString& name)
651 QFileInfo fi(name);
652 QString pgmConfigFile = fi.dirPath(true);
653 if (!pgmConfigFile.isEmpty()) {
654 pgmConfigFile += '/';
656 pgmConfigFile += ".kdbgrc." + fi.fileName();
657 TRACE("program config file = " + pgmConfigFile);
658 return pgmConfigFile;
661 void KDebugger::openProgramConfig(const QString& name)
663 ASSERT(m_programConfig == 0);
665 QString pgmConfigFile = getConfigForExe(name);
666 // check whether we can write to the file
667 QFile file(pgmConfigFile);
668 bool readonly = true;
669 bool openit = true;
670 if (file.open(IO_ReadWrite)) { /* don't truncate! */
671 readonly = false;
672 // the file exists now
673 } else if (!file.open(IO_ReadOnly)) {
674 /* file does not exist and cannot be created: don't use it */
675 openit = false;
677 if (openit) {
678 m_programConfig = new KSimpleConfig(pgmConfigFile, readonly);
682 const char EnvironmentGroup[] = "Environment";
683 const char WatchGroup[] = "Watches";
684 const char FileVersion[] = "FileVersion";
685 const char ProgramArgs[] = "ProgramArgs";
686 const char WorkingDirectory[] = "WorkingDirectory";
687 const char OptionsSelected[] = "OptionsSelected";
688 const char Variable[] = "Var%d";
689 const char Value[] = "Value%d";
690 const char ExprFmt[] = "Expr%d";
692 void KDebugger::saveProgramSettings()
694 ASSERT(m_programConfig != 0);
695 m_programConfig->setGroup(GeneralGroup);
696 m_programConfig->writeEntry(FileVersion, 1);
697 m_programConfig->writeEntry(ProgramArgs, m_programArgs);
698 m_programConfig->writeEntry(WorkingDirectory, m_programWD);
699 m_programConfig->writeEntry(OptionsSelected, m_boolOptions);
700 m_programConfig->writeEntry(DebuggerCmdStr, m_debuggerCmd);
701 m_programConfig->writeEntry(TTYLevelEntry, int(m_ttyLevel));
702 QString driverName;
703 if (m_d != 0)
704 driverName = m_d->driverName();
705 m_programConfig->writeEntry(DriverNameEntry, driverName);
707 // write environment variables
708 m_programConfig->deleteGroup(EnvironmentGroup);
709 m_programConfig->setGroup(EnvironmentGroup);
710 QDictIterator<EnvVar> it = m_envVars;
711 EnvVar* var;
712 QString varName;
713 QString varValue;
714 for (int i = 0; (var = it) != 0; ++it, ++i) {
715 varName.sprintf(Variable, i);
716 varValue.sprintf(Value, i);
717 m_programConfig->writeEntry(varName, it.currentKey());
718 m_programConfig->writeEntry(varValue, var->value);
721 saveBreakpoints(m_programConfig);
723 // watch expressions
724 // first get rid of whatever was in this group
725 m_programConfig->deleteGroup(WatchGroup);
726 // then start a new group
727 m_programConfig->setGroup(WatchGroup);
728 KTreeViewItem* item = m_watchVariables.itemAt(0);
729 int watchNum = 0;
730 for (; item != 0; item = item->getSibling(), ++watchNum) {
731 varName.sprintf(ExprFmt, watchNum);
732 m_programConfig->writeEntry(varName, item->getText());
735 // give others a chance
736 emit saveProgramSpecific(m_programConfig);
739 void KDebugger::restoreProgramSettings()
741 ASSERT(m_programConfig != 0);
742 m_programConfig->setGroup(GeneralGroup);
744 * We ignore file version for now we will use it in the future to
745 * distinguish different versions of this configuration file.
747 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
748 // m_ttyLevel has been read in already
749 QString pgmArgs = m_programConfig->readEntry(ProgramArgs);
750 QString pgmWd = m_programConfig->readEntry(WorkingDirectory);
751 QStringList boolOptions = m_programConfig->readListEntry(OptionsSelected);
752 m_boolOptions = QStringList();
754 // read environment variables
755 m_programConfig->setGroup(EnvironmentGroup);
756 m_envVars.clear();
757 QDict<EnvVar> pgmVars;
758 EnvVar* var;
759 QString varName;
760 QString varValue;
761 for (int i = 0;; ++i) {
762 varName.sprintf(Variable, i);
763 varValue.sprintf(Value, i);
764 if (!m_programConfig->hasKey(varName)) {
765 /* entry not present, assume that we've hit them all */
766 break;
768 QString name = m_programConfig->readEntry(varName);
769 if (name.isEmpty()) {
770 // skip empty names
771 continue;
773 var = new EnvVar;
774 var->value = m_programConfig->readEntry(varValue);
775 var->status = EnvVar::EVnew;
776 pgmVars.insert(name, var);
779 updateProgEnvironment(pgmArgs, pgmWd, pgmVars, boolOptions);
781 restoreBreakpoints(m_programConfig);
783 // watch expressions
784 m_programConfig->setGroup(WatchGroup);
785 m_watchVariables.clear();
786 for (int i = 0;; ++i) {
787 varName.sprintf(ExprFmt, i);
788 if (!m_programConfig->hasKey(varName)) {
789 /* entry not present, assume that we've hit them all */
790 break;
792 QString expr = m_programConfig->readEntry(varName);
793 if (expr.isEmpty()) {
794 // skip empty expressions
795 continue;
797 addWatch(expr);
800 // give others a chance
801 emit restoreProgramSpecific(m_programConfig);
805 * Breakpoints are saved one per group.
807 const char BPGroup[] = "Breakpoint %d";
808 const char File[] = "File";
809 const char Line[] = "Line";
810 const char Text[] = "Text";
811 const char Address[] = "Address";
812 const char Temporary[] = "Temporary";
813 const char Enabled[] = "Enabled";
814 const char Condition[] = "Condition";
816 void KDebugger::saveBreakpoints(KSimpleConfig* config)
818 QString groupName;
819 int i = 0;
820 for (uint j = 0; j < m_brkpts.size(); j++) {
821 Breakpoint* bp = m_brkpts[j];
822 if (bp->type == Breakpoint::watchpoint)
823 continue; /* don't save watchpoints */
824 groupName.sprintf(BPGroup, i++);
826 /* remove remmants */
827 config->deleteGroup(groupName);
829 config->setGroup(groupName);
830 if (!bp->text.isEmpty()) {
832 * The breakpoint was set using the text box in the breakpoint
833 * list. We do not save the location by filename+line number,
834 * but instead honor what the user typed (a function name, for
835 * example, which could move between sessions).
837 config->writeEntry(Text, bp->text);
838 } else if (!bp->fileName.isEmpty()) {
839 config->writeEntry(File, bp->fileName);
840 config->writeEntry(Line, bp->lineNo);
842 * Addresses are hardly correct across sessions, so we don't
843 * save it.
845 } else {
846 config->writeEntry(Address, bp->address.asString());
848 config->writeEntry(Temporary, bp->temporary);
849 config->writeEntry(Enabled, bp->enabled);
850 if (!bp->condition.isEmpty())
851 config->writeEntry(Condition, bp->condition);
852 // we do not save the ignore count
854 // delete remaining groups
855 // we recognize that a group is present if there is an Enabled entry
856 for (;; i++) {
857 groupName.sprintf(BPGroup, i);
858 config->setGroup(groupName);
859 if (!config->hasKey(Enabled)) {
860 /* group not present, assume that we've hit them all */
861 break;
863 config->deleteGroup(groupName);
867 void KDebugger::restoreBreakpoints(KSimpleConfig* config)
869 QString groupName;
871 * We recognize the end of the list if there is no Enabled entry
872 * present.
874 for (int i = 0;; i++) {
875 groupName.sprintf(BPGroup, i);
876 config->setGroup(groupName);
877 if (!config->hasKey(Enabled)) {
878 /* group not present, assume that we've hit them all */
879 break;
881 Breakpoint* bp = new Breakpoint;
882 bp->fileName = config->readEntry(File);
883 bp->lineNo = config->readNumEntry(Line, -1);
884 bp->text = config->readEntry(Text);
885 bp->address = config->readEntry(Address);
886 // check consistency
887 if ((bp->fileName.isEmpty() || bp->lineNo < 0) &&
888 bp->text.isEmpty() &&
889 bp->address.isEmpty())
891 delete bp;
892 continue;
894 bp->enabled = config->readBoolEntry(Enabled, true);
895 bp->temporary = config->readBoolEntry(Temporary, false);
896 bp->condition = config->readEntry(Condition);
899 * Add the breakpoint.
901 setBreakpoint(bp, false);
902 // the new breakpoint is disabled or conditionalized later
903 // in newBreakpoint()
905 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
909 // parse output of command cmd
910 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
912 ASSERT(cmd != 0); /* queue mustn't be empty */
914 TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
916 switch (cmd->m_cmd) {
917 case DCtargetremote:
918 // the output (if any) is uninteresting
919 case DCsetargs:
920 case DCtty:
921 // there is no output
922 case DCsetenv:
923 case DCunsetenv:
924 case DCsetoption:
925 /* if value is empty, we see output, but we don't care */
926 break;
927 case DCcd:
928 /* display gdb's message in the status bar */
929 m_d->parseChangeWD(output, m_statusMessage);
930 emit updateStatusMessage();
931 break;
932 case DCinitialize:
933 break;
934 case DCexecutable:
935 if (m_d->parseChangeExecutable(output, m_statusMessage))
937 // success; restore breakpoints etc.
938 if (m_programConfig != 0) {
939 restoreProgramSettings();
941 // load file containing main() or core file
942 if (m_corefile.isEmpty()) {
943 if (m_remoteDevice.isEmpty())
944 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
945 } else {
946 // load core file
947 loadCoreFile();
949 if (!m_statusMessage.isEmpty())
950 emit updateStatusMessage();
951 } else {
952 QString msg = m_d->driverName() + ": " + m_statusMessage;
953 KMessageBox::sorry(parentWidget(), msg);
954 m_executable = "";
955 m_corefile = ""; /* don't process core file */
956 m_haveExecutable = false;
958 break;
959 case DCcorefile:
960 // in any event we have an executable at this point
961 m_haveExecutable = true;
962 if (m_d->parseCoreFile(output)) {
963 // loading a core is like stopping at a breakpoint
964 m_programActive = true;
965 handleRunCommands(output);
966 // do not reset m_corefile
967 } else {
968 // report error
969 QString msg = m_d->driverName() + ": " + QString(output);
970 KMessageBox::sorry(parentWidget(), msg);
972 // if core file was loaded from command line, revert to info line main
973 if (!cmd->m_byUser) {
974 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
976 m_corefile = QString(); /* core file not available any more */
978 break;
979 case DCinfolinemain:
980 // ignore the output, marked file info follows
981 m_haveExecutable = true;
982 break;
983 case DCinfolocals:
984 // parse local variables
985 if (output[0] != '\0') {
986 handleLocals(output);
988 break;
989 case DCinforegisters:
990 handleRegisters(output);
991 break;
992 case DCexamine:
993 handleMemoryDump(output);
994 break;
995 case DCinfoline:
996 handleInfoLine(cmd, output);
997 break;
998 case DCdisassemble:
999 handleDisassemble(cmd, output);
1000 break;
1001 case DCframe:
1002 handleFrameChange(output);
1003 updateAllExprs();
1004 break;
1005 case DCbt:
1006 handleBacktrace(output);
1007 updateAllExprs();
1008 break;
1009 case DCprint:
1010 handlePrint(cmd, output);
1011 break;
1012 case DCattach:
1013 case DCrun:
1014 case DCcont:
1015 case DCstep:
1016 case DCstepi:
1017 case DCnext:
1018 case DCnexti:
1019 case DCfinish:
1020 case DCuntil:
1021 case DCthread:
1022 handleRunCommands(output);
1023 break;
1024 case DCkill:
1025 m_programRunning = m_programActive = false;
1026 // erase PC
1027 emit updatePC(QString(), -1, DbgAddr(), 0);
1028 break;
1029 case DCbreaktext:
1030 case DCbreakline:
1031 case DCtbreakline:
1032 case DCbreakaddr:
1033 case DCtbreakaddr:
1034 case DCwatchpoint:
1035 newBreakpoint(cmd, output);
1036 // fall through
1037 case DCdelete:
1038 case DCenable:
1039 case DCdisable:
1040 // these commands need immediate response
1041 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverrideMoreEqual);
1042 break;
1043 case DCinfobreak:
1044 // note: this handler must not enqueue a command, since
1045 // DCinfobreak is used at various different places.
1046 updateBreakList(output);
1047 break;
1048 case DCfindType:
1049 handleFindType(cmd, output);
1050 break;
1051 case DCprintStruct:
1052 case DCprintQStringStruct:
1053 handlePrintStruct(cmd, output);
1054 break;
1055 case DCinfosharedlib:
1056 handleSharedLibs(output);
1057 break;
1058 case DCcondition:
1059 case DCignore:
1060 // we are not interested in the output
1061 break;
1062 case DCinfothreads:
1063 handleThreadList(output);
1064 break;
1065 case DCsetpc:
1066 handleSetPC(output);
1067 break;
1071 void KDebugger::backgroundUpdate()
1074 * If there are still expressions that need to be updated, then do so.
1076 if (m_programActive)
1077 evalExpressions();
1080 void KDebugger::handleRunCommands(const char* output)
1082 uint flags = m_d->parseProgramStopped(output, m_statusMessage);
1083 emit updateStatusMessage();
1085 m_programActive = flags & DebuggerDriver::SFprogramActive;
1087 // refresh files if necessary
1088 if (flags & DebuggerDriver::SFrefreshSource) {
1089 TRACE("re-reading files");
1090 emit executableUpdated();
1094 * Try to set any orphaned breakpoints now.
1096 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1097 if (m_brkpts[i]->isOrphaned()) {
1098 TRACE("re-trying brkpt loc: "+m_brkpts[i]->location+
1099 " file: "+m_brkpts[i]->fileName+
1100 QString().sprintf(" line: %d", m_brkpts[i]->lineNo));
1101 setBreakpoint(m_brkpts[i], true);
1102 flags |= DebuggerDriver::SFrefreshBreak;
1107 * If we stopped at a breakpoint, we must update the breakpoint list
1108 * because the hit count changes. Also, if the breakpoint was temporary
1109 * it would go away now.
1111 if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
1112 stopMayChangeBreakList())
1114 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
1118 * If we haven't listed the shared libraries yet, do so. We must do
1119 * this before we emit any commands that list variables, since the type
1120 * libraries depend on the shared libraries.
1122 if (!m_sharedLibsListed) {
1123 // must be a high-priority command!
1124 m_d->executeCmd(DCinfosharedlib);
1127 // get the backtrace if the program is running
1128 if (m_programActive) {
1129 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
1130 } else {
1131 // program finished: erase PC
1132 emit updatePC(QString(), -1, DbgAddr(), 0);
1133 // dequeue any commands in the queues
1134 m_d->flushCommands();
1137 /* Update threads list */
1138 if (flags & DebuggerDriver::SFrefreshThreads) {
1139 m_d->queueCmd(DCinfothreads, DebuggerDriver::QMoverride);
1142 m_programRunning = false;
1143 emit programStopped();
1146 void KDebugger::slotInferiorRunning()
1148 m_programRunning = true;
1151 void KDebugger::updateAllExprs()
1153 if (!m_programActive)
1154 return;
1156 // retrieve local variables
1157 m_d->queueCmd(DCinfolocals, DebuggerDriver::QMoverride);
1159 // retrieve registers
1160 m_d->queueCmd(DCinforegisters, DebuggerDriver::QMoverride);
1162 // get new memory dump
1163 if (!m_memoryExpression.isEmpty()) {
1164 queueMemoryDump(false);
1167 // update watch expressions
1168 KTreeViewItem* item = m_watchVariables.itemAt(0);
1169 for (; item != 0; item = item->getSibling()) {
1170 m_watchEvalExpr.append(static_cast<VarTree*>(item));
1174 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
1175 const QDict<EnvVar>& newVars,
1176 const QStringList& newOptions)
1178 m_programArgs = args;
1179 m_d->executeCmd(DCsetargs, m_programArgs);
1180 TRACE("new pgm args: " + m_programArgs + "\n");
1182 m_programWD = wd.stripWhiteSpace();
1183 if (!m_programWD.isEmpty()) {
1184 m_d->executeCmd(DCcd, m_programWD);
1185 TRACE("new wd: " + m_programWD + "\n");
1188 // update environment variables
1189 QDictIterator<EnvVar> it = newVars;
1190 EnvVar* val;
1191 for (; (val = it) != 0; ++it) {
1192 QString var = it.currentKey();
1193 switch (val->status) {
1194 case EnvVar::EVnew:
1195 m_envVars.insert(var, val);
1196 // fall thru
1197 case EnvVar::EVdirty:
1198 // the value must be in our list
1199 ASSERT(m_envVars[var] == val);
1200 // update value
1201 m_d->executeCmd(DCsetenv, var, val->value);
1202 break;
1203 case EnvVar::EVdeleted:
1204 // must be in our list
1205 ASSERT(m_envVars[var] == val);
1206 // delete value
1207 m_d->executeCmd(DCunsetenv, var);
1208 m_envVars.remove(var);
1209 break;
1210 default:
1211 ASSERT(false);
1212 case EnvVar::EVclean:
1213 // variable not changed
1214 break;
1218 // update options
1219 QStringList::ConstIterator oi;
1220 for (oi = newOptions.begin(); oi != newOptions.end(); ++oi)
1222 if (m_boolOptions.findIndex(*oi) < 0) {
1223 // the options is currently not set, so set it
1224 m_d->executeCmd(DCsetoption, *oi, 1);
1225 } else {
1226 // option is set, no action required, but move it to the end
1227 m_boolOptions.remove(*oi);
1229 m_boolOptions.append(*oi);
1232 * Now all options that should be set are at the end of m_boolOptions.
1233 * If some options need to be unset, they are at the front of the list.
1234 * Here we unset and remove them.
1236 while (m_boolOptions.count() > newOptions.count()) {
1237 m_d->executeCmd(DCsetoption, m_boolOptions.first(), 0);
1238 m_boolOptions.remove(m_boolOptions.begin());
1242 void KDebugger::handleLocals(const char* output)
1244 // retrieve old list of local variables
1245 QStrList oldVars;
1246 m_localVariables.exprList(oldVars);
1249 * Get local variables.
1251 QList<VarTree> newVars;
1252 parseLocals(output, newVars);
1255 * Clear any old VarTree item pointers, so that later we don't access
1256 * dangling pointers.
1258 m_localVariables.clearPendingUpdates();
1260 // reduce flicker
1261 bool autoU = m_localVariables.autoUpdate();
1262 m_localVariables.setAutoUpdate(false);
1263 bool repaintNeeded = false;
1266 * Match old variables against new ones.
1268 for (const char* n = oldVars.first(); n != 0; n = oldVars.next()) {
1269 // lookup this variable in the list of new variables
1270 VarTree* v = newVars.first();
1271 while (v != 0 && strcmp(v->getText(), n) != 0) {
1272 v = newVars.next();
1274 if (v == 0) {
1275 // old variable not in the new variables
1276 TRACE(QString("old var deleted: ") + n);
1277 v = m_localVariables.topLevelExprByName(n);
1278 removeExpr(&m_localVariables, v);
1279 if (v != 0) repaintNeeded = true;
1280 } else {
1281 // variable in both old and new lists: update
1282 TRACE(QString("update var: ") + n);
1283 m_localVariables.updateExpr(newVars.current());
1284 // remove the new variable from the list
1285 newVars.remove();
1286 delete v;
1287 repaintNeeded = true;
1290 // insert all remaining new variables
1291 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1292 TRACE("new var: " + v->getText());
1293 m_localVariables.insertExpr(v);
1294 repaintNeeded = true;
1297 // repaint
1298 m_localVariables.setAutoUpdate(autoU);
1299 if (repaintNeeded && autoU && m_localVariables.isVisible())
1300 m_localVariables.repaint();
1303 void KDebugger::parseLocals(const char* output, QList<VarTree>& newVars)
1305 QList<VarTree> vars;
1306 m_d->parseLocals(output, vars);
1308 QString origName; /* used in renaming variables */
1309 while (vars.count() > 0)
1311 VarTree* variable = vars.take(0);
1312 // get some types
1313 variable->inferTypesOfChildren(*m_typeTable);
1315 * When gdb prints local variables, those from the innermost block
1316 * come first. We run through the list of already parsed variables
1317 * to find duplicates (ie. variables that hide local variables from
1318 * a surrounding block). We keep the name of the inner variable, but
1319 * rename those from the outer block so that, when the value is
1320 * updated in the window, the value of the variable that is
1321 * _visible_ changes the color!
1323 int block = 0;
1324 origName = variable->getText();
1325 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1326 if (variable->getText() == v->getText()) {
1327 // we found a duplicate, change name
1328 block++;
1329 QString newName = origName + " (" + QString().setNum(block) + ")";
1330 variable->setText(newName);
1333 newVars.append(variable);
1337 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1339 ASSERT(cmd->m_expr != 0);
1341 VarTree* variable = parseExpr(output, true);
1342 if (variable == 0)
1343 return false;
1345 // set expression "name"
1346 variable->setText(cmd->m_expr->getText());
1348 if (cmd->m_expr->m_varKind == VarTree::VKpointer) {
1350 * We must insert a dummy parent, because otherwise variable's value
1351 * would overwrite cmd->m_expr's value.
1353 VarTree* dummyParent = new VarTree(variable->getText(), VarTree::NKplain);
1354 dummyParent->m_varKind = VarTree::VKdummy;
1355 // the name of the parsed variable is the address of the pointer
1356 QString addr = "*" + cmd->m_expr->m_value;
1357 variable->setText(addr);
1358 variable->m_nameKind = VarTree::NKaddress;
1360 dummyParent->appendChild(variable);
1361 dummyParent->setDeleteChildren(true);
1362 // expand the first level for convenience
1363 variable->setExpanded(true);
1364 TRACE("update ptr: " + cmd->m_expr->getText());
1365 cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent);
1366 delete dummyParent;
1367 } else {
1368 TRACE("update expr: " + cmd->m_expr->getText());
1369 cmd->m_exprWnd->updateExpr(cmd->m_expr, variable);
1370 delete variable;
1373 evalExpressions(); /* enqueue dereferenced pointers */
1375 return true;
1378 VarTree* KDebugger::parseExpr(const char* output, bool wantErrorValue)
1380 VarTree* variable;
1382 // check for error conditions
1383 bool goodValue = m_d->parsePrintExpr(output, wantErrorValue, variable);
1385 if (variable != 0 && goodValue)
1387 // get some types
1388 variable->inferTypesOfChildren(*m_typeTable);
1390 return variable;
1393 // parse the output of bt
1394 void KDebugger::handleBacktrace(const char* output)
1396 // reduce flicker
1397 m_btWindow.setAutoUpdate(false);
1399 m_btWindow.clear();
1401 QList<StackFrame> stack;
1402 m_d->parseBackTrace(output, stack);
1404 if (stack.count() > 0) {
1405 StackFrame* frm = stack.take(0);
1406 // first frame must set PC
1407 // note: frm->lineNo is zero-based
1408 emit updatePC(frm->fileName, frm->lineNo, frm->address, frm->frameNo);
1410 do {
1411 QString func;
1412 if (frm->var != 0)
1413 func = frm->var->getText();
1414 else
1415 func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1416 m_btWindow.insertItem(func);
1417 TRACE("frame " + func + " (" + frm->fileName + ":" +
1418 QString().setNum(frm->lineNo+1) + ")");
1419 delete frm;
1421 while ((frm = stack.take()) != 0);
1424 m_btWindow.setAutoUpdate(true);
1425 m_btWindow.repaint();
1428 void KDebugger::gotoFrame(int frame)
1430 m_d->executeCmd(DCframe, frame);
1433 void KDebugger::handleFrameChange(const char* output)
1435 QString fileName;
1436 int frameNo;
1437 int lineNo;
1438 DbgAddr address;
1439 if (m_d->parseFrameChange(output, frameNo, fileName, lineNo, address)) {
1440 /* lineNo can be negative here if we can't find a file name */
1441 emit updatePC(fileName, lineNo, address, frameNo);
1442 } else {
1443 emit updatePC(fileName, -1, address, frameNo);
1447 void KDebugger::evalExpressions()
1449 // evaluate expressions in the following order:
1450 // watch expressions
1451 // pointers in local variables
1452 // pointers in watch expressions
1453 // types in local variables
1454 // types in watch expressions
1455 // pointers in 'this'
1456 // types in 'this'
1458 VarTree* exprItem = m_watchEvalExpr.first();
1459 if (exprItem != 0) {
1460 m_watchEvalExpr.remove();
1461 QString expr = exprItem->computeExpr();
1462 TRACE("watch expr: " + expr);
1463 CmdQueueItem* cmd = m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverride);
1464 // remember which expr this was
1465 cmd->m_expr = exprItem;
1466 cmd->m_exprWnd = &m_watchVariables;
1467 } else {
1468 ExprWnd* wnd;
1469 VarTree* exprItem;
1470 #define POINTER(widget) \
1471 wnd = &widget; \
1472 exprItem = widget.nextUpdatePtr(); \
1473 if (exprItem != 0) goto pointer
1474 #define STRUCT(widget) \
1475 wnd = &widget; \
1476 exprItem = widget.nextUpdateStruct(); \
1477 if (exprItem != 0) goto ustruct
1478 #define TYPE(widget) \
1479 wnd = &widget; \
1480 exprItem = widget.nextUpdateType(); \
1481 if (exprItem != 0) goto type
1482 repeat:
1483 POINTER(m_localVariables);
1484 POINTER(m_watchVariables);
1485 STRUCT(m_localVariables);
1486 STRUCT(m_watchVariables);
1487 TYPE(m_localVariables);
1488 TYPE(m_watchVariables);
1489 #undef POINTER
1490 #undef STRUCT
1491 #undef TYPE
1492 return;
1494 pointer:
1495 // we have an expression to send
1496 dereferencePointer(wnd, exprItem, false);
1497 return;
1499 ustruct:
1500 // paranoia
1501 if (exprItem->m_type == 0 || exprItem->m_type == TypeInfo::unknownType())
1502 goto repeat;
1503 evalInitialStructExpression(exprItem, wnd, false);
1504 return;
1506 type:
1508 * Sometimes a VarTree gets registered twice for a type update. So
1509 * it may happen that it has already been updated. Hence, we ignore
1510 * it here and go on to the next task.
1512 if (exprItem->m_type != 0)
1513 goto repeat;
1514 determineType(wnd, exprItem);
1518 void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem,
1519 bool immediate)
1521 ASSERT(exprItem->m_varKind == VarTree::VKpointer);
1523 QString expr = exprItem->computeExpr();
1524 TRACE("dereferencing pointer: " + expr);
1525 QString queueExpr = "*(" + expr + ")";
1526 CmdQueueItem* cmd;
1527 if (immediate) {
1528 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverrideMoreEqual);
1529 } else {
1530 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverride);
1532 // remember which expr this was
1533 cmd->m_expr = exprItem;
1534 cmd->m_exprWnd = wnd;
1537 void KDebugger::determineType(ExprWnd* wnd, VarTree* exprItem)
1539 ASSERT(exprItem->m_varKind == VarTree::VKstruct);
1541 QString expr = exprItem->computeExpr();
1542 TRACE("get type of: " + expr);
1543 CmdQueueItem* cmd;
1544 cmd = m_d->queueCmd(DCfindType, expr, DebuggerDriver::QMoverride);
1546 // remember which expr this was
1547 cmd->m_expr = exprItem;
1548 cmd->m_exprWnd = wnd;
1551 void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output)
1553 QString type;
1554 if (m_d->parseFindType(output, type))
1556 ASSERT(cmd != 0 && cmd->m_expr != 0);
1558 TypeInfo* info = m_typeTable->lookup(type);
1560 if (info == 0) {
1562 * We've asked gdb for the type of the expression in
1563 * cmd->m_expr, but it returned a name we don't know. The base
1564 * class (and member) types have been checked already (at the
1565 * time when we parsed that particular expression). Now it's
1566 * time to derive the type from the base classes as a last
1567 * resort.
1569 info = cmd->m_expr->inferTypeFromBaseClass();
1570 // if we found a type through this method, register an alias
1571 if (info != 0) {
1572 TRACE("infered alias: " + type);
1573 m_typeTable->registerAlias(type, info);
1576 if (info == 0) {
1577 TRACE("unknown type");
1578 cmd->m_expr->m_type = TypeInfo::unknownType();
1579 } else {
1580 cmd->m_expr->m_type = info;
1581 /* since this node has a new type, we get its value immediately */
1582 evalInitialStructExpression(cmd->m_expr, cmd->m_exprWnd, false);
1583 return;
1587 evalExpressions(); /* queue more of them */
1590 void KDebugger::handlePrintStruct(CmdQueueItem* cmd, const char* output)
1592 VarTree* var = cmd->m_expr;
1593 ASSERT(var != 0);
1594 ASSERT(var->m_varKind == VarTree::VKstruct);
1596 VarTree* partExpr;
1597 if (cmd->m_cmd != DCprintQStringStruct) {
1598 partExpr = parseExpr(output, false);
1599 } else {
1600 partExpr = m_d->parseQCharArray(output, false, m_typeTable->qCharIsShort());
1602 bool errorValue =
1603 partExpr == 0 ||
1604 /* we only allow simple values at the moment */
1605 partExpr->childCount() != 0;
1607 QString partValue;
1608 if (errorValue)
1610 partValue = "?""?""?"; // 2 question marks in a row would be a trigraph
1611 } else {
1612 partValue = partExpr->m_value;
1614 delete partExpr;
1615 partExpr = 0;
1618 * Updating a struct value works like this: var->m_partialValue holds
1619 * the value that we have gathered so far (it's been initialized with
1620 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1621 * we append the printed result followed by the next
1622 * var->m_type->m_displayString to var->m_partialValue.
1624 * If the expression we just evaluated was a guard expression, and it
1625 * resulted in an error, we must not evaluate the real expression, but
1626 * go on to the next index. (We must still add the question marks to
1627 * the value).
1629 * Next, if this was the length expression, we still have not seen the
1630 * real expression, but the length of a QString.
1632 ASSERT(var->m_exprIndex >= 0 && var->m_exprIndex <= typeInfoMaxExpr);
1634 if (errorValue || !var->m_exprIndexUseGuard)
1636 // add current partValue (which might be the question marks)
1637 var->m_partialValue += partValue;
1638 var->m_exprIndex++; /* next part */
1639 var->m_exprIndexUseGuard = true;
1640 var->m_partialValue += var->m_type->m_displayString[var->m_exprIndex];
1642 else
1644 // this was a guard expression that succeeded
1645 // go for the real expression
1646 var->m_exprIndexUseGuard = false;
1649 /* go for more sub-expressions if needed */
1650 if (var->m_exprIndex < var->m_type->m_numExprs) {
1651 /* queue a new print command with quite high priority */
1652 evalStructExpression(var, cmd->m_exprWnd, true);
1653 return;
1656 cmd->m_exprWnd->updateStructValue(var);
1658 evalExpressions(); /* enqueue dereferenced pointers */
1661 /* queues the first printStruct command for a struct */
1662 void KDebugger::evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1664 var->m_exprIndex = 0;
1665 var->m_exprIndexUseGuard = true;
1666 var->m_partialValue = var->m_type->m_displayString[0];
1667 evalStructExpression(var, wnd, immediate);
1670 /* queues a printStruct command; var must have been initialized correctly */
1671 void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1673 QString base = var->computeExpr();
1674 QString exprFmt;
1675 if (var->m_exprIndexUseGuard) {
1676 exprFmt = var->m_type->m_guardStrings[var->m_exprIndex];
1677 if (exprFmt.isEmpty()) {
1678 // no guard, omit it and go to expression
1679 var->m_exprIndexUseGuard = false;
1682 if (!var->m_exprIndexUseGuard) {
1683 exprFmt = var->m_type->m_exprStrings[var->m_exprIndex];
1686 SIZED_QString(expr, exprFmt.length() + base.length() + 10);
1687 expr.sprintf(exprFmt, base.data());
1689 DbgCommand dbgCmd = DCprintStruct;
1690 // check if this is a QString::Data
1691 if (strncmp(expr, "/QString::Data ", 15) == 0)
1693 if (m_typeTable->parseQt2QStrings())
1695 expr = expr.mid(15, expr.length()); /* strip off /QString::Data */
1696 dbgCmd = DCprintQStringStruct;
1697 } else {
1699 * This should not happen: the type libraries should be set up
1700 * in a way that this can't happen. If this happens
1701 * nevertheless it means that, eg., kdecore was loaded but qt2
1702 * was not (only qt2 enables the QString feature).
1704 // TODO: remove this "print"; queue the next printStruct instead
1705 expr = "*0";
1707 } else {
1708 expr = expr;
1710 TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1711 CmdQueueItem* cmd = m_d->queueCmd(dbgCmd, expr,
1712 immediate ? DebuggerDriver::QMoverrideMoreEqual
1713 : DebuggerDriver::QMnormal);
1715 // remember which expression this was
1716 cmd->m_expr = var;
1717 cmd->m_exprWnd = wnd;
1720 /* removes expression from window */
1721 void KDebugger::removeExpr(ExprWnd* wnd, VarTree* var)
1723 if (var == 0)
1724 return;
1726 // must remove any references to var from command queues
1727 m_d->dequeueCmdByVar(var);
1729 wnd->removeExpr(var);
1732 void KDebugger::handleSharedLibs(const char* output)
1734 // delete all known libraries
1735 m_sharedLibs.clear();
1737 // parse the table of shared libraries
1738 m_d->parseSharedLibs(output, m_sharedLibs);
1739 m_sharedLibsListed = true;
1741 // get type libraries
1742 m_typeTable->loadLibTypes(m_sharedLibs);
1745 CmdQueueItem* KDebugger::loadCoreFile()
1747 return m_d->queueCmd(DCcorefile, m_corefile, DebuggerDriver::QMoverride);
1750 void KDebugger::slotLocalsExpanding(KTreeViewItem* item, bool& allow)
1752 exprExpandingHelper(&m_localVariables, item, allow);
1755 void KDebugger::slotWatchExpanding(KTreeViewItem* item, bool& allow)
1757 exprExpandingHelper(&m_watchVariables, item, allow);
1760 void KDebugger::exprExpandingHelper(ExprWnd* wnd, KTreeViewItem* item, bool&)
1762 VarTree* exprItem = static_cast<VarTree*>(item);
1763 if (exprItem->m_varKind != VarTree::VKpointer) {
1764 return;
1766 dereferencePointer(wnd, exprItem, true);
1769 // add the expression in the edit field to the watch expressions
1770 void KDebugger::addWatch(const QString& t)
1772 QString expr = t.stripWhiteSpace();
1773 if (expr.isEmpty())
1774 return;
1775 VarTree* exprItem = new VarTree(expr, VarTree::NKplain);
1776 m_watchVariables.insertExpr(exprItem);
1778 // if we are boring ourselves, send down the command
1779 if (m_programActive) {
1780 m_watchEvalExpr.append(exprItem);
1781 if (m_d->isIdle()) {
1782 evalExpressions();
1787 // delete a toplevel watch expression
1788 void KDebugger::slotDeleteWatch()
1790 // delete only allowed while debugger is idle; or else we might delete
1791 // the very expression the debugger is currently working on...
1792 if (!m_d->isIdle())
1793 return;
1795 int index = m_watchVariables.currentItem();
1796 if (index < 0)
1797 return;
1799 VarTree* item = static_cast<VarTree*>(m_watchVariables.itemAt(index));
1800 if (!item->isToplevelExpr())
1801 return;
1803 // remove the variable from the list to evaluate
1804 if (m_watchEvalExpr.findRef(item) >= 0) {
1805 m_watchEvalExpr.remove();
1807 removeExpr(&m_watchVariables, item);
1808 // item is invalid at this point!
1811 void KDebugger::startAnimation(bool fast)
1813 int interval = fast ? 50 : 150;
1814 if (!m_animationTimer.isActive()) {
1815 m_animationTimer.start(interval);
1816 } else if (m_animationInterval != interval) {
1817 m_animationTimer.changeInterval(interval);
1819 m_animationInterval = interval;
1822 void KDebugger::stopAnimation()
1824 if (m_animationTimer.isActive()) {
1825 m_animationTimer.stop();
1826 m_animationInterval = 0;
1830 void KDebugger::slotUpdateAnimation()
1832 if (isIdle()) {
1833 stopAnimation();
1834 } else {
1836 * Slow animation while program is stopped (i.e. while variables
1837 * are displayed)
1839 bool slow = isReady() && m_programActive && !m_programRunning;
1840 startAnimation(!slow);
1844 void KDebugger::handleRegisters(const char* output)
1846 QList<RegisterInfo> regs;
1847 m_d->parseRegisters(output, regs);
1849 emit registersChanged(regs);
1851 // delete them all
1852 regs.setAutoDelete(true);
1856 * The output of the DCbreak* commands has more accurate information about
1857 * the file and the line number.
1859 * All newly set breakpoints are inserted in the m_brkpts, even those that
1860 * were not set sucessfully. The unsuccessful breakpoints ("orphaned
1861 * breakpoints") are assigned negative ids, and they are tried to set later
1862 * when the program stops again at a breakpoint.
1864 void KDebugger::newBreakpoint(CmdQueueItem* cmd, const char* output)
1866 Breakpoint* bp = cmd->m_brkpt;
1867 assert(bp != 0);
1868 if (bp == 0)
1869 return;
1871 // if this is a new breakpoint, put it in the list
1872 bool isNew = !m_brkpts.contains(bp);
1873 if (isNew) {
1874 assert(bp->id == 0);
1875 int n = m_brkpts.size();
1876 m_brkpts.resize(n+1);
1877 m_brkpts.insert(n, bp);
1880 // parse the output to determine success or failure
1881 int id;
1882 QString file;
1883 int lineNo;
1884 QString address;
1885 if (!m_d->parseBreakpoint(output, id, file, lineNo, address))
1888 * Failure, the breakpoint could not be set. If this is a new
1889 * breakpoint, assign it a negative id. We look for the minimal id
1890 * of all breakpoints (that are already in the list) to get the new
1891 * id.
1893 if (isNew)
1895 assert(bp->id == 0);
1896 for (int i = m_brkpts.size()-2; i >= 0; i--) {
1897 if (m_brkpts[i]->id < bp->id) {
1898 bp->id = m_brkpts[i]->id;
1899 break;
1902 --bp->id;
1904 return;
1907 // The breakpoint was successfully set.
1908 if (bp->id <= 0)
1910 // this is a new or orphaned breakpoint:
1911 // set the remaining properties
1912 if (!cmd->m_brkpt->enabled) {
1913 m_d->executeCmd(DCdisable, id);
1915 if (!cmd->m_brkpt->condition.isEmpty()) {
1916 m_d->executeCmd(DCcondition, cmd->m_brkpt->condition, id);
1920 bp->id = id;
1921 bp->fileName = file;
1922 bp->lineNo = lineNo;
1923 if (!address.isEmpty())
1924 bp->address = address;
1927 void KDebugger::updateBreakList(const char* output)
1929 // get the new list
1930 QList<Breakpoint> brks;
1931 brks.setAutoDelete(false);
1932 m_d->parseBreakList(output, brks);
1934 // merge new information into existing breakpoints
1936 for (int i = m_brkpts.size()-1; i >= 0; i--) // decrement!
1938 // skip orphaned breakpoints
1939 if (m_brkpts[i]->id < 0)
1940 continue;
1942 for (Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
1944 if (bp->id == m_brkpts[i]->id) {
1945 // keep accurate location
1946 // except that xsldbg doesn't have a location in
1947 // the old breakpoint if it's just been set
1948 bp->text = m_brkpts[i]->text;
1949 if (!m_brkpts[i]->fileName.isEmpty()) {
1950 bp->fileName = m_brkpts[i]->fileName;
1951 bp->lineNo = m_brkpts[i]->lineNo;
1953 m_brkpts.insert(i, bp); // old object is deleted
1954 goto stillAlive;
1958 * If we get here, this breakpoint is no longer present.
1960 * To delete the breakpoint at i, we place the last breakpoint in
1961 * the list into the slot i. This will delete the old object at i.
1962 * Then we shorten the list by one.
1964 m_brkpts.insert(i, m_brkpts.take(m_brkpts.size()-1));
1965 m_brkpts.resize(m_brkpts.size()-1);
1966 TRACE(QString().sprintf("deleted brkpt %d, have now %d brkpts", i, m_brkpts.size()));
1968 stillAlive:;
1971 // brks may contain new breakpoints not already in m_brkpts
1972 for (const Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
1974 bool found = false;
1975 for (uint i = 0; i < m_brkpts.size(); i++) {
1976 if (bp->id == m_brkpts[i]->id) {
1977 found = true;
1978 break;
1981 if (!found){
1982 int n = m_brkpts.size();
1983 m_brkpts.resize(n+1);
1984 m_brkpts.insert(n, bp);
1988 emit breakpointsChanged();
1991 // look if there is at least one temporary breakpoint
1992 // or a watchpoint
1993 bool KDebugger::stopMayChangeBreakList() const
1995 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1996 Breakpoint* bp = m_brkpts[i];
1997 if (bp->temporary || bp->type == Breakpoint::watchpoint)
1998 return true;
2000 return false;
2003 Breakpoint* KDebugger::breakpointByFilePos(QString file, int lineNo,
2004 const DbgAddr& address)
2006 // look for exact file name match
2007 int i;
2008 for (i = m_brkpts.size()-1; i >= 0; i--) {
2009 if (m_brkpts[i]->lineNo == lineNo &&
2010 m_brkpts[i]->fileName == file &&
2011 (address.isEmpty() || m_brkpts[i]->address == address))
2013 return m_brkpts[i];
2016 // not found, so try basename
2017 // strip off directory part of file name
2018 int offset = file.findRev("/");
2019 file.remove(0, offset+1);
2021 for (i = m_brkpts.size()-1; i >= 0; i--) {
2022 // get base name of breakpoint's file
2023 QString basename = m_brkpts[i]->fileName;
2024 int offset = basename.findRev("/");
2025 if (offset >= 0) {
2026 basename.remove(0, offset+1);
2029 if (m_brkpts[i]->lineNo == lineNo &&
2030 basename == file &&
2031 (address.isEmpty() || m_brkpts[i]->address == address))
2033 return m_brkpts[i];
2037 // not found
2038 return 0;
2041 Breakpoint* KDebugger::breakpointById(int id)
2043 for (int i = m_brkpts.size()-1; i >= 0; i--)
2045 if (m_brkpts[i]->id == id) {
2046 return m_brkpts[i];
2049 // not found
2050 return 0;
2053 void KDebugger::slotValuePopup(const QString& expr)
2055 // search the local variables for a match
2056 VarTree* v = m_localVariables.topLevelExprByName(expr);
2057 if (v == 0) {
2058 // not found, check watch expressions
2059 v = m_watchVariables.topLevelExprByName(expr);
2060 if (v == 0) {
2061 // nothing found; do nothing
2062 return;
2066 // construct the tip
2067 QString tip = v->getText() + " = ";
2068 if (!v->m_value.isEmpty())
2070 tip += v->m_value;
2072 else
2074 // no value: we use some hint
2075 switch (v->m_varKind) {
2076 case VarTree::VKstruct:
2077 tip += "{...}";
2078 break;
2079 case VarTree::VKarray:
2080 tip += "[...]";
2081 break;
2082 default:
2083 tip += "?""?""?"; // 2 question marks in a row would be a trigraph
2084 break;
2087 emit valuePopup(tip);
2090 void KDebugger::slotDisassemble(const QString& fileName, int lineNo)
2092 CmdQueueItem* cmd = m_d->queueCmd(DCinfoline, fileName, lineNo,
2093 DebuggerDriver::QMoverrideMoreEqual);
2094 cmd->m_fileName = fileName;
2095 cmd->m_lineNo = lineNo;
2098 void KDebugger::handleInfoLine(CmdQueueItem* cmd, const char* output)
2100 QString addrFrom, addrTo;
2101 if (cmd->m_lineNo >= 0) {
2102 // disassemble
2103 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2104 // got the address range, now get the real code
2105 CmdQueueItem* c = m_d->queueCmd(DCdisassemble, addrFrom, addrTo,
2106 DebuggerDriver::QMoverrideMoreEqual);
2107 c->m_fileName = cmd->m_fileName;
2108 c->m_lineNo = cmd->m_lineNo;
2109 } else {
2110 // no code
2111 QList<DisassembledCode> empty;
2112 emit disassembled(cmd->m_fileName, cmd->m_lineNo, empty);
2114 } else {
2115 // set program counter
2116 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2117 // move the program counter to the start address
2118 m_d->executeCmd(DCsetpc, addrFrom);
2123 void KDebugger::handleDisassemble(CmdQueueItem* cmd, const char* output)
2125 QList<DisassembledCode> code;
2126 code.setAutoDelete(true);
2127 m_d->parseDisassemble(output, code);
2128 emit disassembled(cmd->m_fileName, cmd->m_lineNo, code);
2131 void KDebugger::handleThreadList(const char* output)
2133 QList<ThreadInfo> threads;
2134 threads.setAutoDelete(true);
2135 m_d->parseThreadList(output, threads);
2136 emit threadsChanged(threads);
2139 void KDebugger::setThread(int id)
2141 m_d->queueCmd(DCthread, id, DebuggerDriver::QMoverrideMoreEqual);
2144 void KDebugger::setMemoryExpression(const QString& memexpr)
2146 m_memoryExpression = memexpr;
2148 // queue the new expression
2149 if (!m_memoryExpression.isEmpty() &&
2150 isProgramActive() &&
2151 !isProgramRunning())
2153 queueMemoryDump(true);
2157 void KDebugger::queueMemoryDump(bool immediate)
2159 m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat,
2160 immediate ? DebuggerDriver::QMoverrideMoreEqual :
2161 DebuggerDriver::QMoverride);
2164 void KDebugger::handleMemoryDump(const char* output)
2166 QList<MemoryDump> memdump;
2167 memdump.setAutoDelete(true);
2168 QString msg = m_d->parseMemoryDump(output, memdump);
2169 emit memoryDumpChanged(msg, memdump);
2172 void KDebugger::setProgramCounter(const QString& file, int line, const DbgAddr& addr)
2174 if (addr.isEmpty()) {
2175 // find address of the specified line
2176 CmdQueueItem* cmd = m_d->executeCmd(DCinfoline, file, line);
2177 cmd->m_lineNo = -1; /* indicates "Set PC" UI command */
2178 } else {
2179 // move the program counter to that address
2180 m_d->executeCmd(DCsetpc, addr.asString());
2184 void KDebugger::handleSetPC(const char* /*output*/)
2186 // TODO: handle errors
2188 // now go to the top-most frame
2189 // this also modifies the program counter indicator in the UI
2190 gotoFrame(0);
2194 #include "debugger.moc"