Don't try to list threads if there is no program.
[kdbg.git] / kdbg / debugger.cpp
bloba3908e309a452cc91ed93e2e395d6b33f2f156eb
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 "programconfig.h"
13 #include "valarray.h"
14 #include <qregexp.h>
15 #include <qfileinfo.h>
16 #include <qlistbox.h>
17 #include <qstringlist.h>
18 #include <kapp.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&)));
57 connect(&m_localVariables, SIGNAL(editValueCommitted(int, const QString&)),
58 SLOT(slotValueEdited(int, const QString&)));
59 connect(&m_watchVariables, SIGNAL(editValueCommitted(int, const QString&)),
60 SLOT(slotValueEdited(int, const QString&)));
62 connect(&m_btWindow, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
64 // animation
65 connect(&m_animationTimer, SIGNAL(timeout()), SIGNAL(animationTimeout()));
66 // special update of animation
67 connect(this, SIGNAL(updateUI()), SLOT(slotUpdateAnimation()));
69 emit updateUI();
72 KDebugger::~KDebugger()
74 if (m_programConfig != 0) {
75 saveProgramSettings();
76 m_programConfig->sync();
77 delete m_programConfig;
80 delete m_typeTable;
84 void KDebugger::saveSettings(KConfig* /*config*/)
88 void KDebugger::restoreSettings(KConfig* /*config*/)
93 //////////////////////////////////////////////////////////////////////
94 // external interface
96 const char GeneralGroup[] = "General";
97 const char DebuggerCmdStr[] = "DebuggerCmdStr";
98 const char TTYLevelEntry[] = "TTYLevel";
99 const char KDebugger::DriverNameEntry[] = "DriverName";
101 bool KDebugger::debugProgram(const QString& name,
102 DebuggerDriver* driver)
104 if (m_d != 0 && m_d->isRunning())
106 QApplication::setOverrideCursor(waitCursor);
108 stopDriver();
110 QApplication::restoreOverrideCursor();
112 if (m_d->isRunning() || m_haveExecutable) {
113 /* timed out! We can't really do anything useful now */
114 TRACE("timed out while waiting for gdb to die!");
115 return false;
117 delete m_d;
118 m_d = 0;
121 // wire up the driver
122 connect(driver, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
123 this, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)));
124 connect(driver, SIGNAL(processExited(KProcess*)), SLOT(gdbExited(KProcess*)));
125 connect(driver, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
126 SLOT(parse(CmdQueueItem*,const char*)));
127 connect(driver, SIGNAL(wroteStdin(KProcess*)), SIGNAL(updateUI()));
128 connect(driver, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
129 connect(driver, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
130 connect(driver, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
132 // create the program settings object
133 openProgramConfig(name);
135 // get debugger command from per-program settings
136 if (m_programConfig != 0) {
137 m_programConfig->setGroup(GeneralGroup);
138 m_debuggerCmd = readDebuggerCmd();
139 // get terminal emulation level
140 m_ttyLevel = TTYLevel(m_programConfig->readNumEntry(TTYLevelEntry, ttyFull));
142 // the rest is read in later in the handler of DCexecutable
144 m_d = driver;
146 if (!startDriver()) {
147 TRACE("startDriver failed");
148 m_d = 0;
149 return false;
152 TRACE("before file cmd");
153 m_d->executeCmd(DCexecutable, name);
154 m_executable = name;
156 // set remote target
157 if (!m_remoteDevice.isEmpty()) {
158 m_d->executeCmd(DCtargetremote, m_remoteDevice);
159 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
160 m_d->queueCmd(DCframe, 0, DebuggerDriver::QMnormal);
161 m_programActive = true;
162 m_haveExecutable = true;
165 // create a type table
166 m_typeTable = new ProgramTypeTable;
167 m_sharedLibsListed = false;
169 emit updateUI();
171 return true;
174 void KDebugger::shutdown()
176 // shut down debugger driver
177 if (m_d != 0 && m_d->isRunning())
179 stopDriver();
183 void KDebugger::useCoreFile(QString corefile, bool batch)
185 m_corefile = corefile;
186 if (!batch) {
187 CmdQueueItem* cmd = loadCoreFile();
188 cmd->m_byUser = true;
192 void KDebugger::setAttachPid(const QString& pid)
194 m_attachedPid = pid;
197 void KDebugger::programRun()
199 if (!isReady())
200 return;
202 // when program is active, but not a core file, continue
203 // otherwise run the program
204 if (m_programActive && m_corefile.isEmpty()) {
205 // gdb command: continue
206 m_d->executeCmd(DCcont, true);
207 } else {
208 // gdb command: run
209 m_d->executeCmd(DCrun, true);
210 m_corefile = QString();
211 m_programActive = true;
213 m_programRunning = true;
216 void KDebugger::attachProgram(const QString& pid)
218 if (!isReady())
219 return;
221 m_attachedPid = pid;
222 TRACE("Attaching to " + m_attachedPid);
223 m_d->executeCmd(DCattach, m_attachedPid);
224 m_programActive = true;
225 m_programRunning = true;
228 void KDebugger::programRunAgain()
230 if (canSingleStep()) {
231 m_d->executeCmd(DCrun, true);
232 m_corefile = QString();
233 m_programRunning = true;
237 void KDebugger::programStep()
239 if (canSingleStep()) {
240 m_d->executeCmd(DCstep, true);
241 m_programRunning = true;
245 void KDebugger::programNext()
247 if (canSingleStep()) {
248 m_d->executeCmd(DCnext, true);
249 m_programRunning = true;
253 void KDebugger::programStepi()
255 if (canSingleStep()) {
256 m_d->executeCmd(DCstepi, true);
257 m_programRunning = true;
261 void KDebugger::programNexti()
263 if (canSingleStep()) {
264 m_d->executeCmd(DCnexti, true);
265 m_programRunning = true;
269 void KDebugger::programFinish()
271 if (canSingleStep()) {
272 m_d->executeCmd(DCfinish, true);
273 m_programRunning = true;
277 void KDebugger::programKill()
279 if (haveExecutable() && isProgramActive()) {
280 if (m_programRunning) {
281 m_d->interruptInferior();
283 // this is an emergency command; flush queues
284 m_d->flushCommands(true);
285 m_d->executeCmd(DCkill, true);
289 bool KDebugger::runUntil(const QString& fileName, int lineNo)
291 if (isReady() && m_programActive && !m_programRunning) {
292 // strip off directory part of file name
293 QString file = fileName;
294 int offset = file.findRev("/");
295 if (offset >= 0) {
296 file.remove(0, offset+1);
298 m_d->executeCmd(DCuntil, file, lineNo, true);
299 m_programRunning = true;
300 return true;
301 } else {
302 return false;
306 void KDebugger::programBreak()
308 if (m_haveExecutable && m_programRunning) {
309 m_d->interruptInferior();
313 void KDebugger::programArgs(QWidget* parent)
315 if (m_haveExecutable) {
316 QStringList allOptions = m_d->boolOptionList();
317 PgmArgs dlg(parent, m_executable, m_envVars, allOptions);
318 dlg.setArgs(m_programArgs);
319 dlg.setWd(m_programWD);
320 dlg.setOptions(m_boolOptions);
321 if (dlg.exec()) {
322 updateProgEnvironment(dlg.args(), dlg.wd(),
323 dlg.envVars(), dlg.options());
328 void KDebugger::programSettings(QWidget* parent)
330 if (!m_haveExecutable)
331 return;
333 ProgramSettings dlg(parent, m_executable);
335 dlg.m_chooseDriver.setDebuggerCmd(m_debuggerCmd);
336 dlg.m_output.setTTYLevel(m_ttyLevel);
338 if (dlg.exec() == QDialog::Accepted)
340 m_debuggerCmd = dlg.m_chooseDriver.debuggerCmd();
341 m_ttyLevel = TTYLevel(dlg.m_output.ttyLevel());
345 bool KDebugger::setBreakpoint(QString file, int lineNo,
346 const DbgAddr& address, bool temporary)
348 if (!isReady()) {
349 return false;
352 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
353 if (bp == 0)
356 * No such breakpoint, so set a new one. If we have an address, we
357 * set the breakpoint exactly there. Otherwise we use the file name
358 * plus line no.
360 Breakpoint* bp = new Breakpoint;
361 bp->temporary = temporary;
363 if (address.isEmpty())
365 bp->fileName = file;
366 bp->lineNo = lineNo;
368 else
370 bp->address = address;
372 setBreakpoint(bp, false);
374 else
377 * If the breakpoint is disabled, enable it; if it's enabled,
378 * delete that breakpoint.
380 if (bp->enabled) {
381 deleteBreakpoint(bp);
382 } else {
383 enableDisableBreakpoint(bp);
386 return true;
389 void KDebugger::setBreakpoint(Breakpoint* bp, bool queueOnly)
391 CmdQueueItem* cmd;
392 if (!bp->text.isEmpty())
395 * The breakpoint was set using the text box in the breakpoint
396 * list. This is the only way in which watchpoints are set.
398 if (bp->type == Breakpoint::watchpoint) {
399 cmd = m_d->executeCmd(DCwatchpoint, bp->text);
400 } else {
401 cmd = m_d->executeCmd(DCbreaktext, bp->text);
404 else if (bp->address.isEmpty())
406 // strip off directory part of file name
407 QString file = bp->fileName;
408 int offset = file.findRev("/");
409 if (offset >= 0) {
410 file.remove(0, offset+1);
412 if (queueOnly) {
413 cmd = m_d->queueCmd(bp->temporary ? DCtbreakline : DCbreakline,
414 file, bp->lineNo, DebuggerDriver::QMoverride);
415 } else {
416 cmd = m_d->executeCmd(bp->temporary ? DCtbreakline : DCbreakline,
417 file, bp->lineNo);
420 else
422 if (queueOnly) {
423 cmd = m_d->queueCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
424 bp->address.asString(), DebuggerDriver::QMoverride);
425 } else {
426 cmd = m_d->executeCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
427 bp->address.asString());
430 cmd->m_brkpt = bp; // used in newBreakpoint()
433 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo,
434 const DbgAddr& address)
436 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
437 return bp == 0 || enableDisableBreakpoint(bp);
440 bool KDebugger::enableDisableBreakpoint(Breakpoint* bp)
443 * Toggle enabled/disabled state.
445 * The driver is not bothered if we are modifying an orphaned
446 * breakpoint.
448 if (!bp->isOrphaned()) {
449 if (!canChangeBreakpoints()) {
450 return false;
452 m_d->executeCmd(bp->enabled ? DCdisable : DCenable, bp->id);
453 } else {
454 bp->enabled = !bp->enabled;
455 emit breakpointsChanged();
457 return true;
460 bool KDebugger::conditionalBreakpoint(Breakpoint* bp,
461 const QString& condition,
462 int ignoreCount)
465 * Change the condition and ignore count.
467 * The driver is not bothered if we are removing an orphaned
468 * breakpoint.
471 if (!bp->isOrphaned()) {
472 if (!canChangeBreakpoints()) {
473 return false;
476 bool changed = false;
478 if (bp->condition != condition) {
479 // change condition
480 m_d->executeCmd(DCcondition, condition, bp->id);
481 changed = true;
483 if (bp->ignoreCount != ignoreCount) {
484 // change ignore count
485 m_d->executeCmd(DCignore, bp->id, ignoreCount);
486 changed = true;
488 if (changed) {
489 // get the changes
490 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
492 } else {
493 bp->condition = condition;
494 bp->ignoreCount = ignoreCount;
495 emit breakpointsChanged();
497 return true;
500 bool KDebugger::deleteBreakpoint(Breakpoint* bp)
503 * Remove the breakpoint.
505 * The driver is not bothered if we are removing an orphaned
506 * breakpoint.
508 if (!bp->isOrphaned()) {
509 if (!canChangeBreakpoints()) {
510 return false;
512 m_d->executeCmd(DCdelete, bp->id);
513 } else {
514 // move the last entry to bp's slot and shorten the list
515 int i = m_brkpts.findRef(bp);
516 m_brkpts.insert(i, m_brkpts.take(m_brkpts.size()-1));
517 m_brkpts.resize(m_brkpts.size()-1);
518 emit breakpointsChanged();
520 return false;
523 bool KDebugger::canSingleStep()
525 return isReady() && m_programActive && !m_programRunning;
528 bool KDebugger::canChangeBreakpoints()
530 return isReady() && !m_programRunning;
533 bool KDebugger::isReady() const
535 return m_haveExecutable &&
536 m_d != 0 && m_d->canExecuteImmediately();
539 bool KDebugger::isIdle() const
541 return m_d == 0 || m_d->isIdle();
545 //////////////////////////////////////////////////////////
546 // debugger driver
548 bool KDebugger::startDriver()
550 emit debuggerStarting(); /* must set m_inferiorTerminal */
553 * If the per-program command string is empty, use the global setting
554 * (which might also be empty, in which case the driver uses its
555 * default).
557 m_explicitKill = false;
558 if (!m_d->startup(m_debuggerCmd)) {
559 return false;
563 * If we have an output terminal, we use it. Otherwise we will run the
564 * program with input and output redirected to /dev/null. Other
565 * redirections are also necessary depending on the tty emulation
566 * level.
568 int redirect = RDNstdin|RDNstdout|RDNstderr; /* redirect everything */
569 if (!m_inferiorTerminal.isEmpty()) {
570 switch (m_ttyLevel) {
571 default:
572 case ttyNone:
573 // redirect everything
574 break;
575 case ttySimpleOutputOnly:
576 redirect = RDNstdin;
577 break;
578 case ttyFull:
579 redirect = 0;
580 break;
583 m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
585 return true;
588 void KDebugger::stopDriver()
590 m_explicitKill = true;
592 if (m_attachedPid.isEmpty()) {
593 m_d->terminate();
594 } else {
595 m_d->detachAndTerminate();
599 * We MUST wait until the slot gdbExited() has been called. But to
600 * avoid a deadlock, we wait only for some certain maximum time. Should
601 * this timeout be reached, the only reasonable thing one could do then
602 * is exiting kdbg.
604 kapp->processEvents(1000); /* ideally, this will already shut it down */
605 int maxTime = 20; /* about 20 seconds */
606 while (m_haveExecutable && maxTime > 0) {
607 // give gdb time to die (and send a SIGCLD)
608 ::sleep(1);
609 --maxTime;
610 kapp->processEvents(1000);
614 void KDebugger::gdbExited(KProcess*)
617 * Save settings, but only if gdb has already processed "info line
618 * main", otherwise we would save an empty config file, because it
619 * isn't read in until then!
621 if (m_programConfig != 0) {
622 if (m_haveExecutable) {
623 saveProgramSettings();
624 m_programConfig->sync();
626 delete m_programConfig;
627 m_programConfig = 0;
630 // erase types
631 delete m_typeTable;
632 m_typeTable = 0;
634 if (m_explicitKill) {
635 TRACE(m_d->driverName() + " exited normally");
636 } else {
637 QString msg = i18n("%1 exited unexpectedly.\n"
638 "Restart the session (e.g. with File|Executable).");
639 KMessageBox::error(parentWidget(), msg.arg(m_d->driverName()));
642 // reset state
643 m_haveExecutable = false;
644 m_executable = "";
645 m_programActive = false;
646 m_programRunning = false;
647 m_explicitKill = false;
648 m_debuggerCmd = QString(); /* use global setting at next start! */
649 m_attachedPid = QString(); /* we are no longer attached to a process */
650 m_ttyLevel = ttyFull;
651 m_brkpts.clear();
653 // stop gear wheel and erase PC
654 stopAnimation();
655 emit updatePC(QString(), -1, DbgAddr(), 0);
658 QString KDebugger::getConfigForExe(const QString& name)
660 QFileInfo fi(name);
661 QString pgmConfigFile = fi.dirPath(true);
662 if (!pgmConfigFile.isEmpty()) {
663 pgmConfigFile += '/';
665 pgmConfigFile += ".kdbgrc." + fi.fileName();
666 TRACE("program config file = " + pgmConfigFile);
667 return pgmConfigFile;
670 void KDebugger::openProgramConfig(const QString& name)
672 ASSERT(m_programConfig == 0);
674 QString pgmConfigFile = getConfigForExe(name);
676 m_programConfig = new ProgramConfig(pgmConfigFile);
679 const char EnvironmentGroup[] = "Environment";
680 const char WatchGroup[] = "Watches";
681 const char FileVersion[] = "FileVersion";
682 const char ProgramArgs[] = "ProgramArgs";
683 const char WorkingDirectory[] = "WorkingDirectory";
684 const char OptionsSelected[] = "OptionsSelected";
685 const char Variable[] = "Var%d";
686 const char Value[] = "Value%d";
687 const char ExprFmt[] = "Expr%d";
689 void KDebugger::saveProgramSettings()
691 ASSERT(m_programConfig != 0);
692 m_programConfig->setGroup(GeneralGroup);
693 m_programConfig->writeEntry(FileVersion, 1);
694 m_programConfig->writeEntry(ProgramArgs, m_programArgs);
695 m_programConfig->writeEntry(WorkingDirectory, m_programWD);
696 m_programConfig->writeEntry(OptionsSelected, m_boolOptions);
697 m_programConfig->writeEntry(DebuggerCmdStr, m_debuggerCmd);
698 m_programConfig->writeEntry(TTYLevelEntry, int(m_ttyLevel));
699 QString driverName;
700 if (m_d != 0)
701 driverName = m_d->driverName();
702 m_programConfig->writeEntry(DriverNameEntry, driverName);
704 // write environment variables
705 m_programConfig->deleteGroup(EnvironmentGroup);
706 m_programConfig->setGroup(EnvironmentGroup);
707 QDictIterator<EnvVar> it = m_envVars;
708 EnvVar* var;
709 QString varName;
710 QString varValue;
711 for (int i = 0; (var = it) != 0; ++it, ++i) {
712 varName.sprintf(Variable, i);
713 varValue.sprintf(Value, i);
714 m_programConfig->writeEntry(varName, it.currentKey());
715 m_programConfig->writeEntry(varValue, var->value);
718 saveBreakpoints(m_programConfig);
720 // watch expressions
721 // first get rid of whatever was in this group
722 m_programConfig->deleteGroup(WatchGroup);
723 // then start a new group
724 m_programConfig->setGroup(WatchGroup);
725 KTreeViewItem* item = m_watchVariables.itemAt(0);
726 int watchNum = 0;
727 for (; item != 0; item = item->getSibling(), ++watchNum) {
728 varName.sprintf(ExprFmt, watchNum);
729 m_programConfig->writeEntry(varName, item->getText());
732 // give others a chance
733 emit saveProgramSpecific(m_programConfig);
736 void KDebugger::restoreProgramSettings()
738 ASSERT(m_programConfig != 0);
739 m_programConfig->setGroup(GeneralGroup);
741 * We ignore file version for now we will use it in the future to
742 * distinguish different versions of this configuration file.
744 // m_debuggerCmd has been read in already
745 // m_ttyLevel has been read in already
746 QString pgmArgs = m_programConfig->readEntry(ProgramArgs);
747 QString pgmWd = m_programConfig->readEntry(WorkingDirectory);
748 QStringList boolOptions = m_programConfig->readListEntry(OptionsSelected);
749 m_boolOptions = QStringList();
751 // read environment variables
752 m_programConfig->setGroup(EnvironmentGroup);
753 m_envVars.clear();
754 QDict<EnvVar> pgmVars;
755 EnvVar* var;
756 QString varName;
757 QString varValue;
758 for (int i = 0;; ++i) {
759 varName.sprintf(Variable, i);
760 varValue.sprintf(Value, i);
761 if (!m_programConfig->hasKey(varName)) {
762 /* entry not present, assume that we've hit them all */
763 break;
765 QString name = m_programConfig->readEntry(varName);
766 if (name.isEmpty()) {
767 // skip empty names
768 continue;
770 var = new EnvVar;
771 var->value = m_programConfig->readEntry(varValue);
772 var->status = EnvVar::EVnew;
773 pgmVars.insert(name, var);
776 updateProgEnvironment(pgmArgs, pgmWd, pgmVars, boolOptions);
778 restoreBreakpoints(m_programConfig);
780 // watch expressions
781 m_programConfig->setGroup(WatchGroup);
782 m_watchVariables.clear();
783 for (int i = 0;; ++i) {
784 varName.sprintf(ExprFmt, i);
785 if (!m_programConfig->hasKey(varName)) {
786 /* entry not present, assume that we've hit them all */
787 break;
789 QString expr = m_programConfig->readEntry(varName);
790 if (expr.isEmpty()) {
791 // skip empty expressions
792 continue;
794 addWatch(expr);
797 // give others a chance
798 emit restoreProgramSpecific(m_programConfig);
802 * Reads the debugger command line from the program settings. The config
803 * group must have been set by the caller.
805 QString KDebugger::readDebuggerCmd()
807 QString debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
809 // always let the user confirm the debugger cmd if we are root
810 if (::geteuid() == 0)
812 if (!debuggerCmd.isEmpty()) {
813 QString msg = i18n(
814 "The settings for this program specify "
815 "the following debugger command:\n%1\n"
816 "Shall this command be used?");
817 if (KMessageBox::warningYesNo(parentWidget(), msg.arg(debuggerCmd))
818 != KMessageBox::Yes)
820 // don't use it
821 debuggerCmd = QString();
825 return debuggerCmd;
829 * Breakpoints are saved one per group.
831 const char BPGroup[] = "Breakpoint %d";
832 const char File[] = "File";
833 const char Line[] = "Line";
834 const char Text[] = "Text";
835 const char Address[] = "Address";
836 const char Temporary[] = "Temporary";
837 const char Enabled[] = "Enabled";
838 const char Condition[] = "Condition";
840 void KDebugger::saveBreakpoints(ProgramConfig* config)
842 QString groupName;
843 int i = 0;
844 for (uint j = 0; j < m_brkpts.size(); j++) {
845 Breakpoint* bp = m_brkpts[j];
846 if (bp->type == Breakpoint::watchpoint)
847 continue; /* don't save watchpoints */
848 groupName.sprintf(BPGroup, i++);
850 /* remove remmants */
851 config->deleteGroup(groupName);
853 config->setGroup(groupName);
854 if (!bp->text.isEmpty()) {
856 * The breakpoint was set using the text box in the breakpoint
857 * list. We do not save the location by filename+line number,
858 * but instead honor what the user typed (a function name, for
859 * example, which could move between sessions).
861 config->writeEntry(Text, bp->text);
862 } else if (!bp->fileName.isEmpty()) {
863 config->writeEntry(File, bp->fileName);
864 config->writeEntry(Line, bp->lineNo);
866 * Addresses are hardly correct across sessions, so we don't
867 * save it.
869 } else {
870 config->writeEntry(Address, bp->address.asString());
872 config->writeEntry(Temporary, bp->temporary);
873 config->writeEntry(Enabled, bp->enabled);
874 if (!bp->condition.isEmpty())
875 config->writeEntry(Condition, bp->condition);
876 // we do not save the ignore count
878 // delete remaining groups
879 // we recognize that a group is present if there is an Enabled entry
880 for (;; i++) {
881 groupName.sprintf(BPGroup, i);
882 config->setGroup(groupName);
883 if (!config->hasKey(Enabled)) {
884 /* group not present, assume that we've hit them all */
885 break;
887 config->deleteGroup(groupName);
891 void KDebugger::restoreBreakpoints(ProgramConfig* config)
893 QString groupName;
895 * We recognize the end of the list if there is no Enabled entry
896 * present.
898 for (int i = 0;; i++) {
899 groupName.sprintf(BPGroup, i);
900 config->setGroup(groupName);
901 if (!config->hasKey(Enabled)) {
902 /* group not present, assume that we've hit them all */
903 break;
905 Breakpoint* bp = new Breakpoint;
906 bp->fileName = config->readEntry(File);
907 bp->lineNo = config->readNumEntry(Line, -1);
908 bp->text = config->readEntry(Text);
909 bp->address = config->readEntry(Address);
910 // check consistency
911 if ((bp->fileName.isEmpty() || bp->lineNo < 0) &&
912 bp->text.isEmpty() &&
913 bp->address.isEmpty())
915 delete bp;
916 continue;
918 bp->enabled = config->readBoolEntry(Enabled, true);
919 bp->temporary = config->readBoolEntry(Temporary, false);
920 bp->condition = config->readEntry(Condition);
923 * Add the breakpoint.
925 setBreakpoint(bp, false);
926 // the new breakpoint is disabled or conditionalized later
927 // in newBreakpoint()
929 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
933 // parse output of command cmd
934 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
936 ASSERT(cmd != 0); /* queue mustn't be empty */
938 TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
940 switch (cmd->m_cmd) {
941 case DCtargetremote:
942 // the output (if any) is uninteresting
943 case DCsetargs:
944 case DCtty:
945 // there is no output
946 case DCsetenv:
947 case DCunsetenv:
948 case DCsetoption:
949 /* if value is empty, we see output, but we don't care */
950 break;
951 case DCcd:
952 /* display gdb's message in the status bar */
953 m_d->parseChangeWD(output, m_statusMessage);
954 emit updateStatusMessage();
955 break;
956 case DCinitialize:
957 break;
958 case DCexecutable:
959 if (m_d->parseChangeExecutable(output, m_statusMessage))
961 // success; restore breakpoints etc.
962 if (m_programConfig != 0) {
963 restoreProgramSettings();
965 // load file containing main() or core file
966 if (!m_corefile.isEmpty())
968 // load core file
969 loadCoreFile();
971 else if (!m_attachedPid.isEmpty())
973 m_d->queueCmd(DCattach, m_attachedPid, DebuggerDriver::QMoverride);
974 m_programActive = true;
975 m_programRunning = true;
977 else if (!m_remoteDevice.isEmpty())
979 // handled elsewhere
981 else
983 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
985 if (!m_statusMessage.isEmpty())
986 emit updateStatusMessage();
987 } else {
988 QString msg = m_d->driverName() + ": " + m_statusMessage;
989 KMessageBox::sorry(parentWidget(), msg);
990 m_executable = "";
991 m_corefile = ""; /* don't process core file */
992 m_haveExecutable = false;
994 break;
995 case DCcorefile:
996 // in any event we have an executable at this point
997 m_haveExecutable = true;
998 if (m_d->parseCoreFile(output)) {
999 // loading a core is like stopping at a breakpoint
1000 m_programActive = true;
1001 handleRunCommands(output);
1002 // do not reset m_corefile
1003 } else {
1004 // report error
1005 QString msg = m_d->driverName() + ": " + QString(output);
1006 KMessageBox::sorry(parentWidget(), msg);
1008 // if core file was loaded from command line, revert to info line main
1009 if (!cmd->m_byUser) {
1010 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
1012 m_corefile = QString(); /* core file not available any more */
1014 break;
1015 case DCinfolinemain:
1016 // ignore the output, marked file info follows
1017 m_haveExecutable = true;
1018 break;
1019 case DCinfolocals:
1020 // parse local variables
1021 if (output[0] != '\0') {
1022 handleLocals(output);
1024 break;
1025 case DCinforegisters:
1026 handleRegisters(output);
1027 break;
1028 case DCexamine:
1029 handleMemoryDump(output);
1030 break;
1031 case DCinfoline:
1032 handleInfoLine(cmd, output);
1033 break;
1034 case DCdisassemble:
1035 handleDisassemble(cmd, output);
1036 break;
1037 case DCframe:
1038 handleFrameChange(output);
1039 updateAllExprs();
1040 break;
1041 case DCbt:
1042 handleBacktrace(output);
1043 updateAllExprs();
1044 break;
1045 case DCprint:
1046 handlePrint(cmd, output);
1047 break;
1048 case DCprintDeref:
1049 handlePrintDeref(cmd, output);
1050 break;
1051 case DCattach:
1052 case DCrun:
1053 case DCcont:
1054 case DCstep:
1055 case DCstepi:
1056 case DCnext:
1057 case DCnexti:
1058 case DCfinish:
1059 case DCuntil:
1060 case DCthread:
1061 handleRunCommands(output);
1062 break;
1063 case DCkill:
1064 m_programRunning = m_programActive = false;
1065 // erase PC
1066 emit updatePC(QString(), -1, DbgAddr(), 0);
1067 break;
1068 case DCbreaktext:
1069 case DCbreakline:
1070 case DCtbreakline:
1071 case DCbreakaddr:
1072 case DCtbreakaddr:
1073 case DCwatchpoint:
1074 newBreakpoint(cmd, output);
1075 // fall through
1076 case DCdelete:
1077 case DCenable:
1078 case DCdisable:
1079 // these commands need immediate response
1080 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverrideMoreEqual);
1081 break;
1082 case DCinfobreak:
1083 // note: this handler must not enqueue a command, since
1084 // DCinfobreak is used at various different places.
1085 updateBreakList(output);
1086 break;
1087 case DCfindType:
1088 handleFindType(cmd, output);
1089 break;
1090 case DCprintStruct:
1091 case DCprintQStringStruct:
1092 handlePrintStruct(cmd, output);
1093 break;
1094 case DCinfosharedlib:
1095 handleSharedLibs(output);
1096 break;
1097 case DCcondition:
1098 case DCignore:
1099 // we are not interested in the output
1100 break;
1101 case DCinfothreads:
1102 handleThreadList(output);
1103 break;
1104 case DCsetpc:
1105 handleSetPC(output);
1106 break;
1107 case DCsetvariable:
1108 handleSetVariable(cmd, output);
1109 break;
1113 void KDebugger::backgroundUpdate()
1116 * If there are still expressions that need to be updated, then do so.
1118 if (m_programActive)
1119 evalExpressions();
1122 void KDebugger::handleRunCommands(const char* output)
1124 uint flags = m_d->parseProgramStopped(output, m_statusMessage);
1125 emit updateStatusMessage();
1127 m_programActive = flags & DebuggerDriver::SFprogramActive;
1129 // refresh files if necessary
1130 if (flags & DebuggerDriver::SFrefreshSource) {
1131 TRACE("re-reading files");
1132 emit executableUpdated();
1136 * Try to set any orphaned breakpoints now.
1138 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1139 if (m_brkpts[i]->isOrphaned()) {
1140 TRACE("re-trying brkpt loc: "+m_brkpts[i]->location+
1141 " file: "+m_brkpts[i]->fileName+
1142 QString().sprintf(" line: %d", m_brkpts[i]->lineNo));
1143 setBreakpoint(m_brkpts[i], true);
1144 flags |= DebuggerDriver::SFrefreshBreak;
1149 * If we stopped at a breakpoint, we must update the breakpoint list
1150 * because the hit count changes. Also, if the breakpoint was temporary
1151 * it would go away now.
1153 if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
1154 stopMayChangeBreakList())
1156 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
1160 * If we haven't listed the shared libraries yet, do so. We must do
1161 * this before we emit any commands that list variables, since the type
1162 * libraries depend on the shared libraries.
1164 if (!m_sharedLibsListed) {
1165 // must be a high-priority command!
1166 m_d->executeCmd(DCinfosharedlib);
1169 // get the backtrace if the program is running
1170 if (m_programActive) {
1171 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
1172 } else {
1173 // program finished: erase PC
1174 emit updatePC(QString(), -1, DbgAddr(), 0);
1175 // dequeue any commands in the queues
1176 m_d->flushCommands();
1179 /* Update threads list */
1180 if (m_programActive && (flags & DebuggerDriver::SFrefreshThreads)) {
1181 m_d->queueCmd(DCinfothreads, DebuggerDriver::QMoverride);
1184 m_programRunning = false;
1185 emit programStopped();
1188 void KDebugger::slotInferiorRunning()
1190 m_programRunning = true;
1193 void KDebugger::updateAllExprs()
1195 if (!m_programActive)
1196 return;
1198 // retrieve local variables
1199 m_d->queueCmd(DCinfolocals, DebuggerDriver::QMoverride);
1201 // retrieve registers
1202 m_d->queueCmd(DCinforegisters, DebuggerDriver::QMoverride);
1204 // get new memory dump
1205 if (!m_memoryExpression.isEmpty()) {
1206 queueMemoryDump(false);
1209 // update watch expressions
1210 KTreeViewItem* item = m_watchVariables.itemAt(0);
1211 for (; item != 0; item = item->getSibling()) {
1212 m_watchEvalExpr.append(static_cast<VarTree*>(item));
1216 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
1217 const QDict<EnvVar>& newVars,
1218 const QStringList& newOptions)
1220 m_programArgs = args;
1221 m_d->executeCmd(DCsetargs, m_programArgs);
1222 TRACE("new pgm args: " + m_programArgs + "\n");
1224 m_programWD = wd.stripWhiteSpace();
1225 if (!m_programWD.isEmpty()) {
1226 m_d->executeCmd(DCcd, m_programWD);
1227 TRACE("new wd: " + m_programWD + "\n");
1230 // update environment variables
1231 QDictIterator<EnvVar> it = newVars;
1232 EnvVar* val;
1233 for (; (val = it) != 0; ++it) {
1234 QString var = it.currentKey();
1235 switch (val->status) {
1236 case EnvVar::EVnew:
1237 m_envVars.insert(var, val);
1238 // fall thru
1239 case EnvVar::EVdirty:
1240 // the value must be in our list
1241 ASSERT(m_envVars[var] == val);
1242 // update value
1243 m_d->executeCmd(DCsetenv, var, val->value);
1244 break;
1245 case EnvVar::EVdeleted:
1246 // must be in our list
1247 ASSERT(m_envVars[var] == val);
1248 // delete value
1249 m_d->executeCmd(DCunsetenv, var);
1250 m_envVars.remove(var);
1251 break;
1252 default:
1253 ASSERT(false);
1254 case EnvVar::EVclean:
1255 // variable not changed
1256 break;
1260 // update options
1261 QStringList::ConstIterator oi;
1262 for (oi = newOptions.begin(); oi != newOptions.end(); ++oi)
1264 if (m_boolOptions.findIndex(*oi) < 0) {
1265 // the options is currently not set, so set it
1266 m_d->executeCmd(DCsetoption, *oi, 1);
1267 } else {
1268 // option is set, no action required, but move it to the end
1269 m_boolOptions.remove(*oi);
1271 m_boolOptions.append(*oi);
1274 * Now all options that should be set are at the end of m_boolOptions.
1275 * If some options need to be unset, they are at the front of the list.
1276 * Here we unset and remove them.
1278 while (m_boolOptions.count() > newOptions.count()) {
1279 m_d->executeCmd(DCsetoption, m_boolOptions.first(), 0);
1280 m_boolOptions.remove(m_boolOptions.begin());
1284 void KDebugger::handleLocals(const char* output)
1286 // retrieve old list of local variables
1287 QStrList oldVars;
1288 m_localVariables.exprList(oldVars);
1291 * Get local variables.
1293 QList<VarTree> newVars;
1294 parseLocals(output, newVars);
1297 * Clear any old VarTree item pointers, so that later we don't access
1298 * dangling pointers.
1300 m_localVariables.clearPendingUpdates();
1302 // reduce flicker
1303 bool autoU = m_localVariables.autoUpdate();
1304 m_localVariables.setAutoUpdate(false);
1305 bool repaintNeeded = false;
1308 * Match old variables against new ones.
1310 for (const char* n = oldVars.first(); n != 0; n = oldVars.next()) {
1311 // lookup this variable in the list of new variables
1312 VarTree* v = newVars.first();
1313 while (v != 0 && strcmp(v->getText(), n) != 0) {
1314 v = newVars.next();
1316 if (v == 0) {
1317 // old variable not in the new variables
1318 TRACE(QString("old var deleted: ") + n);
1319 v = m_localVariables.topLevelExprByName(n);
1320 removeExpr(&m_localVariables, v);
1321 if (v != 0) repaintNeeded = true;
1322 } else {
1323 // variable in both old and new lists: update
1324 TRACE(QString("update var: ") + n);
1325 m_localVariables.updateExpr(newVars.current());
1326 // remove the new variable from the list
1327 newVars.remove();
1328 delete v;
1329 repaintNeeded = true;
1332 // insert all remaining new variables
1333 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1334 TRACE("new var: " + v->getText());
1335 m_localVariables.insertExpr(v);
1336 repaintNeeded = true;
1339 // repaint
1340 m_localVariables.setAutoUpdate(autoU);
1341 if (repaintNeeded && autoU && m_localVariables.isVisible())
1342 m_localVariables.repaint();
1345 void KDebugger::parseLocals(const char* output, QList<VarTree>& newVars)
1347 QList<VarTree> vars;
1348 m_d->parseLocals(output, vars);
1350 QString origName; /* used in renaming variables */
1351 while (vars.count() > 0)
1353 VarTree* variable = vars.take(0);
1354 // get some types
1355 variable->inferTypesOfChildren(*m_typeTable);
1357 * When gdb prints local variables, those from the innermost block
1358 * come first. We run through the list of already parsed variables
1359 * to find duplicates (ie. variables that hide local variables from
1360 * a surrounding block). We keep the name of the inner variable, but
1361 * rename those from the outer block so that, when the value is
1362 * updated in the window, the value of the variable that is
1363 * _visible_ changes the color!
1365 int block = 0;
1366 origName = variable->getText();
1367 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1368 if (variable->getText() == v->getText()) {
1369 // we found a duplicate, change name
1370 block++;
1371 QString newName = origName + " (" + QString().setNum(block) + ")";
1372 variable->setText(newName);
1375 newVars.append(variable);
1379 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1381 ASSERT(cmd->m_expr != 0);
1383 VarTree* variable = parseExpr(output, true);
1384 if (variable == 0)
1385 return false;
1387 // set expression "name"
1388 variable->setText(cmd->m_expr->getText());
1391 TRACE("update expr: " + cmd->m_expr->getText());
1392 cmd->m_exprWnd->updateExpr(cmd->m_expr, variable);
1393 delete variable;
1396 evalExpressions(); /* enqueue dereferenced pointers */
1398 return true;
1401 bool KDebugger::handlePrintDeref(CmdQueueItem* cmd, const char* output)
1403 ASSERT(cmd->m_expr != 0);
1405 VarTree* variable = parseExpr(output, true);
1406 if (variable == 0)
1407 return false;
1409 // set expression "name"
1410 variable->setText(cmd->m_expr->getText());
1414 * We must insert a dummy parent, because otherwise variable's value
1415 * would overwrite cmd->m_expr's value.
1417 VarTree* dummyParent = new VarTree(variable->getText(), VarTree::NKplain);
1418 dummyParent->m_varKind = VarTree::VKdummy;
1419 // the name of the parsed variable is the address of the pointer
1420 QString addr = "*" + cmd->m_expr->m_value;
1421 variable->setText(addr);
1422 variable->m_nameKind = VarTree::NKaddress;
1424 dummyParent->appendChild(variable);
1425 dummyParent->setDeleteChildren(true);
1426 // expand the first level for convenience
1427 variable->setExpanded(true);
1428 TRACE("update ptr: " + cmd->m_expr->getText());
1429 cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent);
1430 delete dummyParent;
1433 evalExpressions(); /* enqueue dereferenced pointers */
1435 return true;
1438 VarTree* KDebugger::parseExpr(const char* output, bool wantErrorValue)
1440 VarTree* variable;
1442 // check for error conditions
1443 bool goodValue = m_d->parsePrintExpr(output, wantErrorValue, variable);
1445 if (variable != 0 && goodValue)
1447 // get some types
1448 variable->inferTypesOfChildren(*m_typeTable);
1450 return variable;
1453 // parse the output of bt
1454 void KDebugger::handleBacktrace(const char* output)
1456 // reduce flicker
1457 m_btWindow.setAutoUpdate(false);
1459 m_btWindow.clear();
1461 QList<StackFrame> stack;
1462 m_d->parseBackTrace(output, stack);
1464 if (stack.count() > 0) {
1465 StackFrame* frm = stack.take(0);
1466 // first frame must set PC
1467 // note: frm->lineNo is zero-based
1468 emit updatePC(frm->fileName, frm->lineNo, frm->address, frm->frameNo);
1470 do {
1471 QString func;
1472 if (frm->var != 0)
1473 func = frm->var->getText();
1474 else
1475 func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1476 m_btWindow.insertItem(func);
1477 TRACE("frame " + func + " (" + frm->fileName + ":" +
1478 QString().setNum(frm->lineNo+1) + ")");
1479 delete frm;
1481 while ((frm = stack.take()) != 0);
1484 m_btWindow.setAutoUpdate(true);
1485 m_btWindow.repaint();
1488 void KDebugger::gotoFrame(int frame)
1490 m_d->executeCmd(DCframe, frame);
1493 void KDebugger::handleFrameChange(const char* output)
1495 QString fileName;
1496 int frameNo;
1497 int lineNo;
1498 DbgAddr address;
1499 if (m_d->parseFrameChange(output, frameNo, fileName, lineNo, address)) {
1500 /* lineNo can be negative here if we can't find a file name */
1501 emit updatePC(fileName, lineNo, address, frameNo);
1502 } else {
1503 emit updatePC(fileName, -1, address, frameNo);
1507 void KDebugger::evalExpressions()
1509 // evaluate expressions in the following order:
1510 // watch expressions
1511 // pointers in local variables
1512 // pointers in watch expressions
1513 // types in local variables
1514 // types in watch expressions
1515 // pointers in 'this'
1516 // types in 'this'
1518 VarTree* exprItem = m_watchEvalExpr.first();
1519 if (exprItem != 0) {
1520 m_watchEvalExpr.remove();
1521 QString expr = exprItem->computeExpr();
1522 TRACE("watch expr: " + expr);
1523 CmdQueueItem* cmd = m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverride);
1524 // remember which expr this was
1525 cmd->m_expr = exprItem;
1526 cmd->m_exprWnd = &m_watchVariables;
1527 } else {
1528 ExprWnd* wnd;
1529 VarTree* exprItem;
1530 #define POINTER(widget) \
1531 wnd = &widget; \
1532 exprItem = widget.nextUpdatePtr(); \
1533 if (exprItem != 0) goto pointer
1534 #define STRUCT(widget) \
1535 wnd = &widget; \
1536 exprItem = widget.nextUpdateStruct(); \
1537 if (exprItem != 0) goto ustruct
1538 #define TYPE(widget) \
1539 wnd = &widget; \
1540 exprItem = widget.nextUpdateType(); \
1541 if (exprItem != 0) goto type
1542 repeat:
1543 POINTER(m_localVariables);
1544 POINTER(m_watchVariables);
1545 STRUCT(m_localVariables);
1546 STRUCT(m_watchVariables);
1547 TYPE(m_localVariables);
1548 TYPE(m_watchVariables);
1549 #undef POINTER
1550 #undef STRUCT
1551 #undef TYPE
1552 return;
1554 pointer:
1555 // we have an expression to send
1556 dereferencePointer(wnd, exprItem, false);
1557 return;
1559 ustruct:
1560 // paranoia
1561 if (exprItem->m_type == 0 || exprItem->m_type == TypeInfo::unknownType())
1562 goto repeat;
1563 evalInitialStructExpression(exprItem, wnd, false);
1564 return;
1566 type:
1568 * Sometimes a VarTree gets registered twice for a type update. So
1569 * it may happen that it has already been updated. Hence, we ignore
1570 * it here and go on to the next task.
1572 if (exprItem->m_type != 0)
1573 goto repeat;
1574 determineType(wnd, exprItem);
1578 void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem,
1579 bool immediate)
1581 ASSERT(exprItem->m_varKind == VarTree::VKpointer);
1583 QString expr = exprItem->computeExpr();
1584 TRACE("dereferencing pointer: " + expr);
1585 CmdQueueItem* cmd;
1586 if (immediate) {
1587 cmd = m_d->queueCmd(DCprintDeref, expr, DebuggerDriver::QMoverrideMoreEqual);
1588 } else {
1589 cmd = m_d->queueCmd(DCprintDeref, expr, DebuggerDriver::QMoverride);
1591 // remember which expr this was
1592 cmd->m_expr = exprItem;
1593 cmd->m_exprWnd = wnd;
1596 void KDebugger::determineType(ExprWnd* wnd, VarTree* exprItem)
1598 ASSERT(exprItem->m_varKind == VarTree::VKstruct);
1600 QString expr = exprItem->computeExpr();
1601 TRACE("get type of: " + expr);
1602 CmdQueueItem* cmd;
1603 cmd = m_d->queueCmd(DCfindType, expr, DebuggerDriver::QMoverride);
1605 // remember which expr this was
1606 cmd->m_expr = exprItem;
1607 cmd->m_exprWnd = wnd;
1610 void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output)
1612 QString type;
1613 if (m_d->parseFindType(output, type))
1615 ASSERT(cmd != 0 && cmd->m_expr != 0);
1617 TypeInfo* info = m_typeTable->lookup(type);
1619 if (info == 0) {
1621 * We've asked gdb for the type of the expression in
1622 * cmd->m_expr, but it returned a name we don't know. The base
1623 * class (and member) types have been checked already (at the
1624 * time when we parsed that particular expression). Now it's
1625 * time to derive the type from the base classes as a last
1626 * resort.
1628 info = cmd->m_expr->inferTypeFromBaseClass();
1629 // if we found a type through this method, register an alias
1630 if (info != 0) {
1631 TRACE("infered alias: " + type);
1632 m_typeTable->registerAlias(type, info);
1635 if (info == 0) {
1636 TRACE("unknown type");
1637 cmd->m_expr->m_type = TypeInfo::unknownType();
1638 } else {
1639 cmd->m_expr->m_type = info;
1640 /* since this node has a new type, we get its value immediately */
1641 evalInitialStructExpression(cmd->m_expr, cmd->m_exprWnd, false);
1642 return;
1646 evalExpressions(); /* queue more of them */
1649 void KDebugger::handlePrintStruct(CmdQueueItem* cmd, const char* output)
1651 VarTree* var = cmd->m_expr;
1652 ASSERT(var != 0);
1653 ASSERT(var->m_varKind == VarTree::VKstruct);
1655 VarTree* partExpr;
1656 if (cmd->m_cmd != DCprintQStringStruct) {
1657 partExpr = parseExpr(output, false);
1658 } else {
1659 partExpr = m_d->parseQCharArray(output, false, m_typeTable->qCharIsShort());
1661 bool errorValue =
1662 partExpr == 0 ||
1663 /* we only allow simple values at the moment */
1664 partExpr->childCount() != 0;
1666 QString partValue;
1667 if (errorValue)
1669 partValue = "?""?""?"; // 2 question marks in a row would be a trigraph
1670 } else {
1671 partValue = partExpr->m_value;
1673 delete partExpr;
1674 partExpr = 0;
1677 * Updating a struct value works like this: var->m_partialValue holds
1678 * the value that we have gathered so far (it's been initialized with
1679 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1680 * we append the printed result followed by the next
1681 * var->m_type->m_displayString to var->m_partialValue.
1683 * If the expression we just evaluated was a guard expression, and it
1684 * resulted in an error, we must not evaluate the real expression, but
1685 * go on to the next index. (We must still add the question marks to
1686 * the value).
1688 * Next, if this was the length expression, we still have not seen the
1689 * real expression, but the length of a QString.
1691 ASSERT(var->m_exprIndex >= 0 && var->m_exprIndex <= typeInfoMaxExpr);
1693 if (errorValue || !var->m_exprIndexUseGuard)
1695 // add current partValue (which might be the question marks)
1696 var->m_partialValue += partValue;
1697 var->m_exprIndex++; /* next part */
1698 var->m_exprIndexUseGuard = true;
1699 var->m_partialValue += var->m_type->m_displayString[var->m_exprIndex];
1701 else
1703 // this was a guard expression that succeeded
1704 // go for the real expression
1705 var->m_exprIndexUseGuard = false;
1708 /* go for more sub-expressions if needed */
1709 if (var->m_exprIndex < var->m_type->m_numExprs) {
1710 /* queue a new print command with quite high priority */
1711 evalStructExpression(var, cmd->m_exprWnd, true);
1712 return;
1715 cmd->m_exprWnd->updateStructValue(var);
1717 evalExpressions(); /* enqueue dereferenced pointers */
1720 /* queues the first printStruct command for a struct */
1721 void KDebugger::evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1723 var->m_exprIndex = 0;
1724 var->m_exprIndexUseGuard = true;
1725 var->m_partialValue = var->m_type->m_displayString[0];
1726 evalStructExpression(var, wnd, immediate);
1729 /* queues a printStruct command; var must have been initialized correctly */
1730 void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1732 QString base = var->computeExpr();
1733 QString exprFmt;
1734 if (var->m_exprIndexUseGuard) {
1735 exprFmt = var->m_type->m_guardStrings[var->m_exprIndex];
1736 if (exprFmt.isEmpty()) {
1737 // no guard, omit it and go to expression
1738 var->m_exprIndexUseGuard = false;
1741 if (!var->m_exprIndexUseGuard) {
1742 exprFmt = var->m_type->m_exprStrings[var->m_exprIndex];
1745 SIZED_QString(expr, exprFmt.length() + base.length() + 10);
1746 expr.sprintf(exprFmt, base.data());
1748 DbgCommand dbgCmd = DCprintStruct;
1749 // check if this is a QString::Data
1750 if (strncmp(expr, "/QString::Data ", 15) == 0)
1752 if (m_typeTable->parseQt2QStrings())
1754 expr = expr.mid(15, expr.length()); /* strip off /QString::Data */
1755 dbgCmd = DCprintQStringStruct;
1756 } else {
1758 * This should not happen: the type libraries should be set up
1759 * in a way that this can't happen. If this happens
1760 * nevertheless it means that, eg., kdecore was loaded but qt2
1761 * was not (only qt2 enables the QString feature).
1763 // TODO: remove this "print"; queue the next printStruct instead
1764 expr = "*0";
1766 } else {
1767 expr = expr;
1769 TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1770 CmdQueueItem* cmd = m_d->queueCmd(dbgCmd, expr,
1771 immediate ? DebuggerDriver::QMoverrideMoreEqual
1772 : DebuggerDriver::QMnormal);
1774 // remember which expression this was
1775 cmd->m_expr = var;
1776 cmd->m_exprWnd = wnd;
1779 /* removes expression from window */
1780 void KDebugger::removeExpr(ExprWnd* wnd, VarTree* var)
1782 if (var == 0)
1783 return;
1785 // must remove any references to var from command queues
1786 m_d->dequeueCmdByVar(var);
1788 wnd->removeExpr(var);
1791 void KDebugger::handleSharedLibs(const char* output)
1793 // delete all known libraries
1794 m_sharedLibs.clear();
1796 // parse the table of shared libraries
1797 m_d->parseSharedLibs(output, m_sharedLibs);
1798 m_sharedLibsListed = true;
1800 // get type libraries
1801 m_typeTable->loadLibTypes(m_sharedLibs);
1804 CmdQueueItem* KDebugger::loadCoreFile()
1806 return m_d->queueCmd(DCcorefile, m_corefile, DebuggerDriver::QMoverride);
1809 void KDebugger::slotLocalsExpanding(KTreeViewItem* item, bool& allow)
1811 exprExpandingHelper(&m_localVariables, item, allow);
1814 void KDebugger::slotWatchExpanding(KTreeViewItem* item, bool& allow)
1816 exprExpandingHelper(&m_watchVariables, item, allow);
1819 void KDebugger::exprExpandingHelper(ExprWnd* wnd, KTreeViewItem* item, bool&)
1821 VarTree* exprItem = static_cast<VarTree*>(item);
1822 if (exprItem->m_varKind != VarTree::VKpointer) {
1823 return;
1825 dereferencePointer(wnd, exprItem, true);
1828 // add the expression in the edit field to the watch expressions
1829 void KDebugger::addWatch(const QString& t)
1831 QString expr = t.stripWhiteSpace();
1832 if (expr.isEmpty())
1833 return;
1834 VarTree* exprItem = new VarTree(expr, VarTree::NKplain);
1835 m_watchVariables.insertExpr(exprItem);
1837 // if we are boring ourselves, send down the command
1838 if (m_programActive) {
1839 m_watchEvalExpr.append(exprItem);
1840 if (m_d->isIdle()) {
1841 evalExpressions();
1846 // delete a toplevel watch expression
1847 void KDebugger::slotDeleteWatch()
1849 // delete only allowed while debugger is idle; or else we might delete
1850 // the very expression the debugger is currently working on...
1851 if (!m_d->isIdle())
1852 return;
1854 int index = m_watchVariables.currentItem();
1855 if (index < 0)
1856 return;
1858 VarTree* item = static_cast<VarTree*>(m_watchVariables.itemAt(index));
1859 if (!item->isToplevelExpr())
1860 return;
1862 // remove the variable from the list to evaluate
1863 if (m_watchEvalExpr.findRef(item) >= 0) {
1864 m_watchEvalExpr.remove();
1866 removeExpr(&m_watchVariables, item);
1867 // item is invalid at this point!
1870 void KDebugger::startAnimation(bool fast)
1872 int interval = fast ? 50 : 150;
1873 if (!m_animationTimer.isActive()) {
1874 m_animationTimer.start(interval);
1875 } else if (m_animationInterval != interval) {
1876 m_animationTimer.changeInterval(interval);
1878 m_animationInterval = interval;
1881 void KDebugger::stopAnimation()
1883 if (m_animationTimer.isActive()) {
1884 m_animationTimer.stop();
1885 m_animationInterval = 0;
1889 void KDebugger::slotUpdateAnimation()
1891 if (isIdle()) {
1892 stopAnimation();
1893 } else {
1895 * Slow animation while program is stopped (i.e. while variables
1896 * are displayed)
1898 bool slow = isReady() && m_programActive && !m_programRunning;
1899 startAnimation(!slow);
1903 void KDebugger::handleRegisters(const char* output)
1905 QList<RegisterInfo> regs;
1906 m_d->parseRegisters(output, regs);
1908 emit registersChanged(regs);
1910 // delete them all
1911 regs.setAutoDelete(true);
1915 * The output of the DCbreak* commands has more accurate information about
1916 * the file and the line number.
1918 * All newly set breakpoints are inserted in the m_brkpts, even those that
1919 * were not set sucessfully. The unsuccessful breakpoints ("orphaned
1920 * breakpoints") are assigned negative ids, and they are tried to set later
1921 * when the program stops again at a breakpoint.
1923 void KDebugger::newBreakpoint(CmdQueueItem* cmd, const char* output)
1925 Breakpoint* bp = cmd->m_brkpt;
1926 assert(bp != 0);
1927 if (bp == 0)
1928 return;
1930 // if this is a new breakpoint, put it in the list
1931 bool isNew = !m_brkpts.contains(bp);
1932 if (isNew) {
1933 assert(bp->id == 0);
1934 int n = m_brkpts.size();
1935 m_brkpts.resize(n+1);
1936 m_brkpts.insert(n, bp);
1939 // parse the output to determine success or failure
1940 int id;
1941 QString file;
1942 int lineNo;
1943 QString address;
1944 if (!m_d->parseBreakpoint(output, id, file, lineNo, address))
1947 * Failure, the breakpoint could not be set. If this is a new
1948 * breakpoint, assign it a negative id. We look for the minimal id
1949 * of all breakpoints (that are already in the list) to get the new
1950 * id.
1952 if (isNew)
1954 assert(bp->id == 0);
1955 for (int i = m_brkpts.size()-2; i >= 0; i--) {
1956 if (m_brkpts[i]->id < bp->id) {
1957 bp->id = m_brkpts[i]->id;
1958 break;
1961 --bp->id;
1963 return;
1966 // The breakpoint was successfully set.
1967 if (bp->id <= 0)
1969 // this is a new or orphaned breakpoint:
1970 // set the remaining properties
1971 if (!cmd->m_brkpt->enabled) {
1972 m_d->executeCmd(DCdisable, id);
1974 if (!cmd->m_brkpt->condition.isEmpty()) {
1975 m_d->executeCmd(DCcondition, cmd->m_brkpt->condition, id);
1979 bp->id = id;
1980 bp->fileName = file;
1981 bp->lineNo = lineNo;
1982 if (!address.isEmpty())
1983 bp->address = address;
1986 void KDebugger::updateBreakList(const char* output)
1988 // get the new list
1989 QList<Breakpoint> brks;
1990 brks.setAutoDelete(false);
1991 m_d->parseBreakList(output, brks);
1993 // merge new information into existing breakpoints
1995 for (int i = m_brkpts.size()-1; i >= 0; i--) // decrement!
1997 // skip orphaned breakpoints
1998 if (m_brkpts[i]->id < 0)
1999 continue;
2001 for (Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
2003 if (bp->id == m_brkpts[i]->id) {
2004 // keep accurate location
2005 // except that xsldbg doesn't have a location in
2006 // the old breakpoint if it's just been set
2007 bp->text = m_brkpts[i]->text;
2008 if (!m_brkpts[i]->fileName.isEmpty()) {
2009 bp->fileName = m_brkpts[i]->fileName;
2010 bp->lineNo = m_brkpts[i]->lineNo;
2012 m_brkpts.insert(i, bp); // old object is deleted
2013 goto stillAlive;
2017 * If we get here, this breakpoint is no longer present.
2019 * To delete the breakpoint at i, we place the last breakpoint in
2020 * the list into the slot i. This will delete the old object at i.
2021 * Then we shorten the list by one.
2023 m_brkpts.insert(i, m_brkpts.take(m_brkpts.size()-1));
2024 m_brkpts.resize(m_brkpts.size()-1);
2025 TRACE(QString().sprintf("deleted brkpt %d, have now %d brkpts", i, m_brkpts.size()));
2027 stillAlive:;
2030 // brks may contain new breakpoints not already in m_brkpts
2031 for (const Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
2033 bool found = false;
2034 for (uint i = 0; i < m_brkpts.size(); i++) {
2035 if (bp->id == m_brkpts[i]->id) {
2036 found = true;
2037 break;
2040 if (!found){
2041 int n = m_brkpts.size();
2042 m_brkpts.resize(n+1);
2043 m_brkpts.insert(n, bp);
2047 emit breakpointsChanged();
2050 // look if there is at least one temporary breakpoint
2051 // or a watchpoint
2052 bool KDebugger::stopMayChangeBreakList() const
2054 for (int i = m_brkpts.size()-1; i >= 0; i--) {
2055 Breakpoint* bp = m_brkpts[i];
2056 if (bp->temporary || bp->type == Breakpoint::watchpoint)
2057 return true;
2059 return false;
2062 Breakpoint* KDebugger::breakpointByFilePos(QString file, int lineNo,
2063 const DbgAddr& address)
2065 // look for exact file name match
2066 int i;
2067 for (i = m_brkpts.size()-1; i >= 0; i--) {
2068 if (m_brkpts[i]->lineNo == lineNo &&
2069 m_brkpts[i]->fileName == file &&
2070 (address.isEmpty() || m_brkpts[i]->address == address))
2072 return m_brkpts[i];
2075 // not found, so try basename
2076 // strip off directory part of file name
2077 int offset = file.findRev("/");
2078 file.remove(0, offset+1);
2080 for (i = m_brkpts.size()-1; i >= 0; i--) {
2081 // get base name of breakpoint's file
2082 QString basename = m_brkpts[i]->fileName;
2083 int offset = basename.findRev("/");
2084 if (offset >= 0) {
2085 basename.remove(0, offset+1);
2088 if (m_brkpts[i]->lineNo == lineNo &&
2089 basename == file &&
2090 (address.isEmpty() || m_brkpts[i]->address == address))
2092 return m_brkpts[i];
2096 // not found
2097 return 0;
2100 Breakpoint* KDebugger::breakpointById(int id)
2102 for (int i = m_brkpts.size()-1; i >= 0; i--)
2104 if (m_brkpts[i]->id == id) {
2105 return m_brkpts[i];
2108 // not found
2109 return 0;
2112 void KDebugger::slotValuePopup(const QString& expr)
2114 // search the local variables for a match
2115 VarTree* v = m_localVariables.topLevelExprByName(expr);
2116 if (v == 0) {
2117 // not found, check watch expressions
2118 v = m_watchVariables.topLevelExprByName(expr);
2119 if (v == 0) {
2120 // nothing found; do nothing
2121 return;
2125 // construct the tip
2126 QString tip = v->getText() + " = ";
2127 if (!v->m_value.isEmpty())
2129 tip += v->m_value;
2131 else
2133 // no value: we use some hint
2134 switch (v->m_varKind) {
2135 case VarTree::VKstruct:
2136 tip += "{...}";
2137 break;
2138 case VarTree::VKarray:
2139 tip += "[...]";
2140 break;
2141 default:
2142 tip += "?""?""?"; // 2 question marks in a row would be a trigraph
2143 break;
2146 emit valuePopup(tip);
2149 void KDebugger::slotDisassemble(const QString& fileName, int lineNo)
2151 CmdQueueItem* cmd = m_d->queueCmd(DCinfoline, fileName, lineNo,
2152 DebuggerDriver::QMoverrideMoreEqual);
2153 cmd->m_fileName = fileName;
2154 cmd->m_lineNo = lineNo;
2157 void KDebugger::handleInfoLine(CmdQueueItem* cmd, const char* output)
2159 QString addrFrom, addrTo;
2160 if (cmd->m_lineNo >= 0) {
2161 // disassemble
2162 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2163 // got the address range, now get the real code
2164 CmdQueueItem* c = m_d->queueCmd(DCdisassemble, addrFrom, addrTo,
2165 DebuggerDriver::QMoverrideMoreEqual);
2166 c->m_fileName = cmd->m_fileName;
2167 c->m_lineNo = cmd->m_lineNo;
2168 } else {
2169 // no code
2170 QList<DisassembledCode> empty;
2171 emit disassembled(cmd->m_fileName, cmd->m_lineNo, empty);
2173 } else {
2174 // set program counter
2175 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2176 // move the program counter to the start address
2177 m_d->executeCmd(DCsetpc, addrFrom);
2182 void KDebugger::handleDisassemble(CmdQueueItem* cmd, const char* output)
2184 QList<DisassembledCode> code;
2185 code.setAutoDelete(true);
2186 m_d->parseDisassemble(output, code);
2187 emit disassembled(cmd->m_fileName, cmd->m_lineNo, code);
2190 void KDebugger::handleThreadList(const char* output)
2192 QList<ThreadInfo> threads;
2193 threads.setAutoDelete(true);
2194 m_d->parseThreadList(output, threads);
2195 emit threadsChanged(threads);
2198 void KDebugger::setThread(int id)
2200 m_d->queueCmd(DCthread, id, DebuggerDriver::QMoverrideMoreEqual);
2203 void KDebugger::setMemoryExpression(const QString& memexpr)
2205 m_memoryExpression = memexpr;
2207 // queue the new expression
2208 if (!m_memoryExpression.isEmpty() &&
2209 isProgramActive() &&
2210 !isProgramRunning())
2212 queueMemoryDump(true);
2216 void KDebugger::queueMemoryDump(bool immediate)
2218 m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat,
2219 immediate ? DebuggerDriver::QMoverrideMoreEqual :
2220 DebuggerDriver::QMoverride);
2223 void KDebugger::handleMemoryDump(const char* output)
2225 QList<MemoryDump> memdump;
2226 memdump.setAutoDelete(true);
2227 QString msg = m_d->parseMemoryDump(output, memdump);
2228 emit memoryDumpChanged(msg, memdump);
2231 void KDebugger::setProgramCounter(const QString& file, int line, const DbgAddr& addr)
2233 if (addr.isEmpty()) {
2234 // find address of the specified line
2235 CmdQueueItem* cmd = m_d->executeCmd(DCinfoline, file, line);
2236 cmd->m_lineNo = -1; /* indicates "Set PC" UI command */
2237 } else {
2238 // move the program counter to that address
2239 m_d->executeCmd(DCsetpc, addr.asString());
2243 void KDebugger::handleSetPC(const char* /*output*/)
2245 // TODO: handle errors
2247 // now go to the top-most frame
2248 // this also modifies the program counter indicator in the UI
2249 gotoFrame(0);
2252 void KDebugger::slotValueEdited(int row, const QString& text)
2254 if (text.simplifyWhiteSpace().isEmpty())
2255 return; /* no text entered: ignore request */
2257 ASSERT(sender()->inherits("ExprWnd"));
2258 ExprWnd* wnd = const_cast<ExprWnd*>(static_cast<const ExprWnd*>(sender()));
2259 TRACE(QString().sprintf("Changing %s at row %d to ",
2260 wnd->name(), row) + text);
2262 // determine the lvalue to edit
2263 VarTree* expr = static_cast<VarTree*>(wnd->itemAt(row));
2264 QString lvalue = expr->computeExpr();
2265 CmdQueueItem* cmd = m_d->executeCmd(DCsetvariable, lvalue, text);
2266 cmd->m_expr = expr;
2267 cmd->m_exprWnd = wnd;
2270 void KDebugger::handleSetVariable(CmdQueueItem* cmd, const char* output)
2272 QString msg = m_d->parseSetVariable(output);
2273 if (!msg.isEmpty())
2275 // there was an error; display it in the status bar
2276 m_statusMessage = msg;
2277 emit updateStatusMessage();
2278 return;
2281 // get the new value
2282 QString expr = cmd->m_expr->computeExpr();
2283 CmdQueueItem* printCmd =
2284 m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverrideMoreEqual);
2285 printCmd->m_expr = cmd->m_expr;
2286 printCmd->m_exprWnd = cmd->m_exprWnd;
2290 #include "debugger.moc"