Merge with version 2.0.
[kdbg.git] / kdbg / debugger.cpp
blob82ca6cd067c09f6a8839180a7f1415cf1b4ffab3
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)
48 m_envVars.setAutoDelete(true);
49 m_brkpts.setAutoDelete(true);
51 connect(&m_localVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
52 SLOT(slotLocalsExpanding(KTreeViewItem*,bool&)));
53 connect(&m_watchVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
54 SLOT(slotWatchExpanding(KTreeViewItem*,bool&)));
55 connect(&m_localVariables, SIGNAL(editValueCommitted(int, const QString&)),
56 SLOT(slotValueEdited(int, const QString&)));
57 connect(&m_watchVariables, SIGNAL(editValueCommitted(int, const QString&)),
58 SLOT(slotValueEdited(int, const QString&)));
60 connect(&m_btWindow, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
62 emit updateUI();
65 KDebugger::~KDebugger()
67 if (m_programConfig != 0) {
68 saveProgramSettings();
69 m_programConfig->sync();
70 delete m_programConfig;
73 delete m_typeTable;
77 void KDebugger::saveSettings(KConfig* /*config*/)
81 void KDebugger::restoreSettings(KConfig* /*config*/)
86 //////////////////////////////////////////////////////////////////////
87 // external interface
89 const char GeneralGroup[] = "General";
90 const char DebuggerCmdStr[] = "DebuggerCmdStr";
91 const char TTYLevelEntry[] = "TTYLevel";
92 const char KDebugger::DriverNameEntry[] = "DriverName";
94 bool KDebugger::debugProgram(const QString& name,
95 DebuggerDriver* driver)
97 if (m_d != 0 && m_d->isRunning())
99 QApplication::setOverrideCursor(waitCursor);
101 stopDriver();
103 QApplication::restoreOverrideCursor();
105 if (m_d->isRunning() || m_haveExecutable) {
106 /* timed out! We can't really do anything useful now */
107 TRACE("timed out while waiting for gdb to die!");
108 return false;
110 delete m_d;
111 m_d = 0;
114 // wire up the driver
115 connect(driver, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
116 this, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)));
117 connect(driver, SIGNAL(processExited(KProcess*)), SLOT(gdbExited(KProcess*)));
118 connect(driver, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
119 SLOT(parse(CmdQueueItem*,const char*)));
120 connect(driver, SIGNAL(wroteStdin(KProcess*)), SIGNAL(updateUI()));
121 connect(driver, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
122 connect(driver, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
123 connect(driver, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
124 connect(&m_localVariables, SIGNAL(removingItem(VarTree*)),
125 driver, SLOT(dequeueCmdByVar(VarTree*)));
126 connect(&m_watchVariables, SIGNAL(removingItem(VarTree*)),
127 driver, SLOT(dequeueCmdByVar(VarTree*)));
129 // create the program settings object
130 openProgramConfig(name);
132 // get debugger command from per-program settings
133 if (m_programConfig != 0) {
134 m_programConfig->setGroup(GeneralGroup);
135 m_debuggerCmd = readDebuggerCmd();
136 // get terminal emulation level
137 m_ttyLevel = TTYLevel(m_programConfig->readNumEntry(TTYLevelEntry, ttyFull));
139 // the rest is read in later in the handler of DCexecutable
141 m_d = driver;
143 if (!startDriver()) {
144 TRACE("startDriver failed");
145 m_d = 0;
146 return false;
149 TRACE("before file cmd");
150 m_d->executeCmd(DCexecutable, name);
151 m_executable = name;
153 // set remote target
154 if (!m_remoteDevice.isEmpty()) {
155 m_d->executeCmd(DCtargetremote, m_remoteDevice);
156 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
157 m_d->queueCmd(DCframe, 0, DebuggerDriver::QMnormal);
158 m_programActive = true;
159 m_haveExecutable = true;
162 // create a type table
163 m_typeTable = new ProgramTypeTable;
164 m_sharedLibsListed = false;
166 emit updateUI();
168 return true;
171 void KDebugger::shutdown()
173 // shut down debugger driver
174 if (m_d != 0 && m_d->isRunning())
176 stopDriver();
180 void KDebugger::useCoreFile(QString corefile, bool batch)
182 m_corefile = corefile;
183 if (!batch) {
184 CmdQueueItem* cmd = loadCoreFile();
185 cmd->m_byUser = true;
189 void KDebugger::setAttachPid(const QString& pid)
191 m_attachedPid = pid;
194 void KDebugger::programRun()
196 if (!isReady())
197 return;
199 // when program is active, but not a core file, continue
200 // otherwise run the program
201 if (m_programActive && m_corefile.isEmpty()) {
202 // gdb command: continue
203 m_d->executeCmd(DCcont, true);
204 } else {
205 // gdb command: run
206 m_d->executeCmd(DCrun, true);
207 m_corefile = QString();
208 m_programActive = true;
210 m_programRunning = true;
213 void KDebugger::attachProgram(const QString& pid)
215 if (!isReady())
216 return;
218 m_attachedPid = pid;
219 TRACE("Attaching to " + m_attachedPid);
220 m_d->executeCmd(DCattach, m_attachedPid);
221 m_programActive = true;
222 m_programRunning = true;
225 void KDebugger::programRunAgain()
227 if (canSingleStep()) {
228 m_d->executeCmd(DCrun, true);
229 m_corefile = QString();
230 m_programRunning = true;
234 void KDebugger::programStep()
236 if (canSingleStep()) {
237 m_d->executeCmd(DCstep, true);
238 m_programRunning = true;
242 void KDebugger::programNext()
244 if (canSingleStep()) {
245 m_d->executeCmd(DCnext, true);
246 m_programRunning = true;
250 void KDebugger::programStepi()
252 if (canSingleStep()) {
253 m_d->executeCmd(DCstepi, true);
254 m_programRunning = true;
258 void KDebugger::programNexti()
260 if (canSingleStep()) {
261 m_d->executeCmd(DCnexti, true);
262 m_programRunning = true;
266 void KDebugger::programFinish()
268 if (canSingleStep()) {
269 m_d->executeCmd(DCfinish, true);
270 m_programRunning = true;
274 void KDebugger::programKill()
276 if (haveExecutable() && isProgramActive()) {
277 if (m_programRunning) {
278 m_d->interruptInferior();
280 // this is an emergency command; flush queues
281 m_d->flushCommands(true);
282 m_d->executeCmd(DCkill, true);
286 bool KDebugger::runUntil(const QString& fileName, int lineNo)
288 if (isReady() && m_programActive && !m_programRunning) {
289 // strip off directory part of file name
290 QString file = fileName;
291 int offset = file.findRev("/");
292 if (offset >= 0) {
293 file.remove(0, offset+1);
295 m_d->executeCmd(DCuntil, file, lineNo, true);
296 m_programRunning = true;
297 return true;
298 } else {
299 return false;
303 void KDebugger::programBreak()
305 if (m_haveExecutable && m_programRunning) {
306 m_d->interruptInferior();
310 void KDebugger::programArgs(QWidget* parent)
312 if (m_haveExecutable) {
313 QStringList allOptions = m_d->boolOptionList();
314 PgmArgs dlg(parent, m_executable, m_envVars, allOptions);
315 dlg.setArgs(m_programArgs);
316 dlg.setWd(m_programWD);
317 dlg.setOptions(m_boolOptions);
318 if (dlg.exec()) {
319 updateProgEnvironment(dlg.args(), dlg.wd(),
320 dlg.envVars(), dlg.options());
325 void KDebugger::programSettings(QWidget* parent)
327 if (!m_haveExecutable)
328 return;
330 ProgramSettings dlg(parent, m_executable);
332 dlg.m_chooseDriver.setDebuggerCmd(m_debuggerCmd);
333 dlg.m_output.setTTYLevel(m_ttyLevel);
335 if (dlg.exec() == QDialog::Accepted)
337 m_debuggerCmd = dlg.m_chooseDriver.debuggerCmd();
338 m_ttyLevel = TTYLevel(dlg.m_output.ttyLevel());
342 bool KDebugger::setBreakpoint(QString file, int lineNo,
343 const DbgAddr& address, bool temporary)
345 if (!isReady()) {
346 return false;
349 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
350 if (bp == 0)
353 * No such breakpoint, so set a new one. If we have an address, we
354 * set the breakpoint exactly there. Otherwise we use the file name
355 * plus line no.
357 Breakpoint* bp = new Breakpoint;
358 bp->temporary = temporary;
360 if (address.isEmpty())
362 bp->fileName = file;
363 bp->lineNo = lineNo;
365 else
367 bp->address = address;
369 setBreakpoint(bp, false);
371 else
374 * If the breakpoint is disabled, enable it; if it's enabled,
375 * delete that breakpoint.
377 if (bp->enabled) {
378 deleteBreakpoint(bp);
379 } else {
380 enableDisableBreakpoint(bp);
383 return true;
386 void KDebugger::setBreakpoint(Breakpoint* bp, bool queueOnly)
388 CmdQueueItem* cmd;
389 if (!bp->text.isEmpty())
392 * The breakpoint was set using the text box in the breakpoint
393 * list. This is the only way in which watchpoints are set.
395 if (bp->type == Breakpoint::watchpoint) {
396 cmd = m_d->executeCmd(DCwatchpoint, bp->text);
397 } else {
398 cmd = m_d->executeCmd(DCbreaktext, bp->text);
401 else if (bp->address.isEmpty())
403 // strip off directory part of file name
404 QString file = bp->fileName;
405 int offset = file.findRev("/");
406 if (offset >= 0) {
407 file.remove(0, offset+1);
409 if (queueOnly) {
410 cmd = m_d->queueCmd(bp->temporary ? DCtbreakline : DCbreakline,
411 file, bp->lineNo, DebuggerDriver::QMoverride);
412 } else {
413 cmd = m_d->executeCmd(bp->temporary ? DCtbreakline : DCbreakline,
414 file, bp->lineNo);
417 else
419 if (queueOnly) {
420 cmd = m_d->queueCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
421 bp->address.asString(), DebuggerDriver::QMoverride);
422 } else {
423 cmd = m_d->executeCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
424 bp->address.asString());
427 cmd->m_brkpt = bp; // used in newBreakpoint()
430 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo,
431 const DbgAddr& address)
433 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
434 return bp == 0 || enableDisableBreakpoint(bp);
437 bool KDebugger::enableDisableBreakpoint(Breakpoint* bp)
440 * Toggle enabled/disabled state.
442 * The driver is not bothered if we are modifying an orphaned
443 * breakpoint.
445 if (!bp->isOrphaned()) {
446 if (!canChangeBreakpoints()) {
447 return false;
449 m_d->executeCmd(bp->enabled ? DCdisable : DCenable, bp->id);
450 } else {
451 bp->enabled = !bp->enabled;
452 emit breakpointsChanged();
454 return true;
457 bool KDebugger::conditionalBreakpoint(Breakpoint* bp,
458 const QString& condition,
459 int ignoreCount)
462 * Change the condition and ignore count.
464 * The driver is not bothered if we are removing an orphaned
465 * breakpoint.
468 if (!bp->isOrphaned()) {
469 if (!canChangeBreakpoints()) {
470 return false;
473 bool changed = false;
475 if (bp->condition != condition) {
476 // change condition
477 m_d->executeCmd(DCcondition, condition, bp->id);
478 changed = true;
480 if (bp->ignoreCount != ignoreCount) {
481 // change ignore count
482 m_d->executeCmd(DCignore, bp->id, ignoreCount);
483 changed = true;
485 if (changed) {
486 // get the changes
487 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
489 } else {
490 bp->condition = condition;
491 bp->ignoreCount = ignoreCount;
492 emit breakpointsChanged();
494 return true;
497 bool KDebugger::deleteBreakpoint(Breakpoint* bp)
500 * Remove the breakpoint.
502 * The driver is not bothered if we are removing an orphaned
503 * breakpoint.
505 if (!bp->isOrphaned()) {
506 if (!canChangeBreakpoints()) {
507 return false;
509 m_d->executeCmd(DCdelete, bp->id);
510 } else {
511 // move the last entry to bp's slot and shorten the list
512 int i = m_brkpts.findRef(bp);
513 m_brkpts.insert(i, m_brkpts.take(m_brkpts.size()-1));
514 m_brkpts.resize(m_brkpts.size()-1);
515 emit breakpointsChanged();
517 return false;
520 bool KDebugger::canSingleStep()
522 return isReady() && m_programActive && !m_programRunning;
525 bool KDebugger::canChangeBreakpoints()
527 return isReady() && !m_programRunning;
530 bool KDebugger::canStart()
532 return isReady() && !m_programActive;
535 bool KDebugger::isReady() const
537 return m_haveExecutable &&
538 m_d != 0 && m_d->canExecuteImmediately();
541 bool KDebugger::isIdle() const
543 return m_d == 0 || m_d->isIdle();
547 //////////////////////////////////////////////////////////
548 // debugger driver
550 bool KDebugger::startDriver()
552 emit debuggerStarting(); /* must set m_inferiorTerminal */
555 * If the per-program command string is empty, use the global setting
556 * (which might also be empty, in which case the driver uses its
557 * default).
559 m_explicitKill = false;
560 if (!m_d->startup(m_debuggerCmd)) {
561 return false;
565 * If we have an output terminal, we use it. Otherwise we will run the
566 * program with input and output redirected to /dev/null. Other
567 * redirections are also necessary depending on the tty emulation
568 * level.
570 int redirect = RDNstdin|RDNstdout|RDNstderr; /* redirect everything */
571 if (!m_inferiorTerminal.isEmpty()) {
572 switch (m_ttyLevel) {
573 default:
574 case ttyNone:
575 // redirect everything
576 break;
577 case ttySimpleOutputOnly:
578 redirect = RDNstdin;
579 break;
580 case ttyFull:
581 redirect = 0;
582 break;
585 m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
587 return true;
590 void KDebugger::stopDriver()
592 m_explicitKill = true;
594 if (m_attachedPid.isEmpty()) {
595 m_d->terminate();
596 } else {
597 m_d->detachAndTerminate();
601 * We MUST wait until the slot gdbExited() has been called. But to
602 * avoid a deadlock, we wait only for some certain maximum time. Should
603 * this timeout be reached, the only reasonable thing one could do then
604 * is exiting kdbg.
606 kapp->processEvents(1000); /* ideally, this will already shut it down */
607 int maxTime = 20; /* about 20 seconds */
608 while (m_haveExecutable && maxTime > 0) {
609 // give gdb time to die (and send a SIGCLD)
610 ::sleep(1);
611 --maxTime;
612 kapp->processEvents(1000);
616 void KDebugger::gdbExited(KProcess*)
619 * Save settings, but only if gdb has already processed "info line
620 * main", otherwise we would save an empty config file, because it
621 * isn't read in until then!
623 if (m_programConfig != 0) {
624 if (m_haveExecutable) {
625 saveProgramSettings();
626 m_programConfig->sync();
628 delete m_programConfig;
629 m_programConfig = 0;
632 // erase types
633 delete m_typeTable;
634 m_typeTable = 0;
636 if (m_explicitKill) {
637 TRACE(m_d->driverName() + " exited normally");
638 } else {
639 QString msg = i18n("%1 exited unexpectedly.\n"
640 "Restart the session (e.g. with File|Executable).");
641 KMessageBox::error(parentWidget(), msg.arg(m_d->driverName()));
644 // reset state
645 m_haveExecutable = false;
646 m_executable = "";
647 m_programActive = false;
648 m_programRunning = false;
649 m_explicitKill = false;
650 m_debuggerCmd = QString(); /* use global setting at next start! */
651 m_attachedPid = QString(); /* we are no longer attached to a process */
652 m_ttyLevel = ttyFull;
653 m_brkpts.clear();
655 // erase PC
656 emit updatePC(QString(), -1, DbgAddr(), 0);
659 QString KDebugger::getConfigForExe(const QString& name)
661 QFileInfo fi(name);
662 QString pgmConfigFile = fi.dirPath(true);
663 if (!pgmConfigFile.isEmpty()) {
664 pgmConfigFile += '/';
666 pgmConfigFile += ".kdbgrc." + fi.fileName();
667 TRACE("program config file = " + pgmConfigFile);
668 return pgmConfigFile;
671 void KDebugger::openProgramConfig(const QString& name)
673 ASSERT(m_programConfig == 0);
675 QString pgmConfigFile = getConfigForExe(name);
677 m_programConfig = new ProgramConfig(pgmConfigFile);
680 const char EnvironmentGroup[] = "Environment";
681 const char WatchGroup[] = "Watches";
682 const char FileVersion[] = "FileVersion";
683 const char ProgramArgs[] = "ProgramArgs";
684 const char WorkingDirectory[] = "WorkingDirectory";
685 const char OptionsSelected[] = "OptionsSelected";
686 const char Variable[] = "Var%d";
687 const char Value[] = "Value%d";
688 const char ExprFmt[] = "Expr%d";
690 void KDebugger::saveProgramSettings()
692 ASSERT(m_programConfig != 0);
693 m_programConfig->setGroup(GeneralGroup);
694 m_programConfig->writeEntry(FileVersion, 1);
695 m_programConfig->writeEntry(ProgramArgs, m_programArgs);
696 m_programConfig->writeEntry(WorkingDirectory, m_programWD);
697 m_programConfig->writeEntry(OptionsSelected, m_boolOptions);
698 m_programConfig->writeEntry(DebuggerCmdStr, m_debuggerCmd);
699 m_programConfig->writeEntry(TTYLevelEntry, int(m_ttyLevel));
700 QString driverName;
701 if (m_d != 0)
702 driverName = m_d->driverName();
703 m_programConfig->writeEntry(DriverNameEntry, driverName);
705 // write environment variables
706 m_programConfig->deleteGroup(EnvironmentGroup);
707 m_programConfig->setGroup(EnvironmentGroup);
708 QDictIterator<EnvVar> it = m_envVars;
709 EnvVar* var;
710 QString varName;
711 QString varValue;
712 for (int i = 0; (var = it) != 0; ++it, ++i) {
713 varName.sprintf(Variable, i);
714 varValue.sprintf(Value, i);
715 m_programConfig->writeEntry(varName, it.currentKey());
716 m_programConfig->writeEntry(varValue, var->value);
719 saveBreakpoints(m_programConfig);
721 // watch expressions
722 // first get rid of whatever was in this group
723 m_programConfig->deleteGroup(WatchGroup);
724 // then start a new group
725 m_programConfig->setGroup(WatchGroup);
726 KTreeViewItem* item = m_watchVariables.itemAt(0);
727 int watchNum = 0;
728 for (; item != 0; item = item->getSibling(), ++watchNum) {
729 varName.sprintf(ExprFmt, watchNum);
730 m_programConfig->writeEntry(varName, item->getText());
733 // give others a chance
734 emit saveProgramSpecific(m_programConfig);
737 void KDebugger::restoreProgramSettings()
739 ASSERT(m_programConfig != 0);
740 m_programConfig->setGroup(GeneralGroup);
742 * We ignore file version for now we will use it in the future to
743 * distinguish different versions of this configuration file.
745 // m_debuggerCmd has been read in already
746 // m_ttyLevel has been read in already
747 QString pgmArgs = m_programConfig->readEntry(ProgramArgs);
748 QString pgmWd = m_programConfig->readEntry(WorkingDirectory);
749 QStringList boolOptions = m_programConfig->readListEntry(OptionsSelected);
750 m_boolOptions = QStringList();
752 // read environment variables
753 m_programConfig->setGroup(EnvironmentGroup);
754 m_envVars.clear();
755 QDict<EnvVar> pgmVars;
756 EnvVar* var;
757 QString varName;
758 QString varValue;
759 for (int i = 0;; ++i) {
760 varName.sprintf(Variable, i);
761 varValue.sprintf(Value, i);
762 if (!m_programConfig->hasKey(varName)) {
763 /* entry not present, assume that we've hit them all */
764 break;
766 QString name = m_programConfig->readEntry(varName);
767 if (name.isEmpty()) {
768 // skip empty names
769 continue;
771 var = new EnvVar;
772 var->value = m_programConfig->readEntry(varValue);
773 var->status = EnvVar::EVnew;
774 pgmVars.insert(name, var);
777 updateProgEnvironment(pgmArgs, pgmWd, pgmVars, boolOptions);
779 restoreBreakpoints(m_programConfig);
781 // watch expressions
782 m_programConfig->setGroup(WatchGroup);
783 m_watchVariables.clear();
784 for (int i = 0;; ++i) {
785 varName.sprintf(ExprFmt, i);
786 if (!m_programConfig->hasKey(varName)) {
787 /* entry not present, assume that we've hit them all */
788 break;
790 QString expr = m_programConfig->readEntry(varName);
791 if (expr.isEmpty()) {
792 // skip empty expressions
793 continue;
795 addWatch(expr);
798 // give others a chance
799 emit restoreProgramSpecific(m_programConfig);
803 * Reads the debugger command line from the program settings. The config
804 * group must have been set by the caller.
806 QString KDebugger::readDebuggerCmd()
808 QString debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
810 // always let the user confirm the debugger cmd if we are root
811 if (::geteuid() == 0)
813 if (!debuggerCmd.isEmpty()) {
814 QString msg = i18n(
815 "The settings for this program specify "
816 "the following debugger command:\n%1\n"
817 "Shall this command be used?");
818 if (KMessageBox::warningYesNo(parentWidget(), msg.arg(debuggerCmd))
819 != KMessageBox::Yes)
821 // don't use it
822 debuggerCmd = QString();
826 return debuggerCmd;
830 * Breakpoints are saved one per group.
832 const char BPGroup[] = "Breakpoint %d";
833 const char File[] = "File";
834 const char Line[] = "Line";
835 const char Text[] = "Text";
836 const char Address[] = "Address";
837 const char Temporary[] = "Temporary";
838 const char Enabled[] = "Enabled";
839 const char Condition[] = "Condition";
841 void KDebugger::saveBreakpoints(ProgramConfig* config)
843 QString groupName;
844 int i = 0;
845 for (uint j = 0; j < m_brkpts.size(); j++) {
846 Breakpoint* bp = m_brkpts[j];
847 if (bp->type == Breakpoint::watchpoint)
848 continue; /* don't save watchpoints */
849 groupName.sprintf(BPGroup, i++);
851 /* remove remmants */
852 config->deleteGroup(groupName);
854 config->setGroup(groupName);
855 if (!bp->text.isEmpty()) {
857 * The breakpoint was set using the text box in the breakpoint
858 * list. We do not save the location by filename+line number,
859 * but instead honor what the user typed (a function name, for
860 * example, which could move between sessions).
862 config->writeEntry(Text, bp->text);
863 } else if (!bp->fileName.isEmpty()) {
864 config->writeEntry(File, bp->fileName);
865 config->writeEntry(Line, bp->lineNo);
867 * Addresses are hardly correct across sessions, so we don't
868 * save it.
870 } else {
871 config->writeEntry(Address, bp->address.asString());
873 config->writeEntry(Temporary, bp->temporary);
874 config->writeEntry(Enabled, bp->enabled);
875 if (!bp->condition.isEmpty())
876 config->writeEntry(Condition, bp->condition);
877 // we do not save the ignore count
879 // delete remaining groups
880 // we recognize that a group is present if there is an Enabled entry
881 for (;; i++) {
882 groupName.sprintf(BPGroup, i);
883 config->setGroup(groupName);
884 if (!config->hasKey(Enabled)) {
885 /* group not present, assume that we've hit them all */
886 break;
888 config->deleteGroup(groupName);
892 void KDebugger::restoreBreakpoints(ProgramConfig* config)
894 QString groupName;
896 * We recognize the end of the list if there is no Enabled entry
897 * present.
899 for (int i = 0;; i++) {
900 groupName.sprintf(BPGroup, i);
901 config->setGroup(groupName);
902 if (!config->hasKey(Enabled)) {
903 /* group not present, assume that we've hit them all */
904 break;
906 Breakpoint* bp = new Breakpoint;
907 bp->fileName = config->readEntry(File);
908 bp->lineNo = config->readNumEntry(Line, -1);
909 bp->text = config->readEntry(Text);
910 bp->address = config->readEntry(Address);
911 // check consistency
912 if ((bp->fileName.isEmpty() || bp->lineNo < 0) &&
913 bp->text.isEmpty() &&
914 bp->address.isEmpty())
916 delete bp;
917 continue;
919 bp->enabled = config->readBoolEntry(Enabled, true);
920 bp->temporary = config->readBoolEntry(Temporary, false);
921 bp->condition = config->readEntry(Condition);
924 * Add the breakpoint.
926 setBreakpoint(bp, false);
927 // the new breakpoint is disabled or conditionalized later
928 // in newBreakpoint()
930 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
934 // parse output of command cmd
935 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
937 ASSERT(cmd != 0); /* queue mustn't be empty */
939 TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
941 switch (cmd->m_cmd) {
942 case DCtargetremote:
943 // the output (if any) is uninteresting
944 case DCsetargs:
945 case DCtty:
946 // there is no output
947 case DCsetenv:
948 case DCunsetenv:
949 case DCsetoption:
950 /* if value is empty, we see output, but we don't care */
951 break;
952 case DCcd:
953 /* display gdb's message in the status bar */
954 m_d->parseChangeWD(output, m_statusMessage);
955 emit updateStatusMessage();
956 break;
957 case DCinitialize:
958 break;
959 case DCexecutable:
960 if (m_d->parseChangeExecutable(output, m_statusMessage))
962 // success; restore breakpoints etc.
963 if (m_programConfig != 0) {
964 restoreProgramSettings();
966 // load file containing main() or core file
967 if (!m_corefile.isEmpty())
969 // load core file
970 loadCoreFile();
972 else if (!m_attachedPid.isEmpty())
974 m_d->queueCmd(DCattach, m_attachedPid, DebuggerDriver::QMoverride);
975 m_programActive = true;
976 m_programRunning = true;
978 else if (!m_remoteDevice.isEmpty())
980 // handled elsewhere
982 else
984 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
986 if (!m_statusMessage.isEmpty())
987 emit updateStatusMessage();
988 } else {
989 QString msg = m_d->driverName() + ": " + m_statusMessage;
990 KMessageBox::sorry(parentWidget(), msg);
991 m_executable = "";
992 m_corefile = ""; /* don't process core file */
993 m_haveExecutable = false;
995 break;
996 case DCcorefile:
997 // in any event we have an executable at this point
998 m_haveExecutable = true;
999 if (m_d->parseCoreFile(output)) {
1000 // loading a core is like stopping at a breakpoint
1001 m_programActive = true;
1002 handleRunCommands(output);
1003 // do not reset m_corefile
1004 } else {
1005 // report error
1006 QString msg = m_d->driverName() + ": " + QString(output);
1007 KMessageBox::sorry(parentWidget(), msg);
1009 // if core file was loaded from command line, revert to info line main
1010 if (!cmd->m_byUser) {
1011 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
1013 m_corefile = QString(); /* core file not available any more */
1015 break;
1016 case DCinfolinemain:
1017 // ignore the output, marked file info follows
1018 m_haveExecutable = true;
1019 break;
1020 case DCinfolocals:
1021 // parse local variables
1022 if (output[0] != '\0') {
1023 handleLocals(output);
1025 break;
1026 case DCinforegisters:
1027 handleRegisters(output);
1028 break;
1029 case DCexamine:
1030 handleMemoryDump(output);
1031 break;
1032 case DCinfoline:
1033 handleInfoLine(cmd, output);
1034 break;
1035 case DCdisassemble:
1036 handleDisassemble(cmd, output);
1037 break;
1038 case DCframe:
1039 handleFrameChange(output);
1040 updateAllExprs();
1041 break;
1042 case DCbt:
1043 handleBacktrace(output);
1044 updateAllExprs();
1045 break;
1046 case DCprint:
1047 handlePrint(cmd, output);
1048 break;
1049 case DCprintDeref:
1050 handlePrintDeref(cmd, output);
1051 break;
1052 case DCattach:
1053 m_haveExecutable = true;
1054 // fall through
1055 case DCrun:
1056 case DCcont:
1057 case DCstep:
1058 case DCstepi:
1059 case DCnext:
1060 case DCnexti:
1061 case DCfinish:
1062 case DCuntil:
1063 case DCthread:
1064 handleRunCommands(output);
1065 break;
1066 case DCkill:
1067 m_programRunning = m_programActive = false;
1068 // erase PC
1069 emit updatePC(QString(), -1, DbgAddr(), 0);
1070 break;
1071 case DCbreaktext:
1072 case DCbreakline:
1073 case DCtbreakline:
1074 case DCbreakaddr:
1075 case DCtbreakaddr:
1076 case DCwatchpoint:
1077 newBreakpoint(cmd, output);
1078 // fall through
1079 case DCdelete:
1080 case DCenable:
1081 case DCdisable:
1082 // these commands need immediate response
1083 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverrideMoreEqual);
1084 break;
1085 case DCinfobreak:
1086 // note: this handler must not enqueue a command, since
1087 // DCinfobreak is used at various different places.
1088 updateBreakList(output);
1089 break;
1090 case DCfindType:
1091 handleFindType(cmd, output);
1092 break;
1093 case DCprintStruct:
1094 case DCprintQStringStruct:
1095 case DCprintWChar:
1096 handlePrintStruct(cmd, output);
1097 break;
1098 case DCinfosharedlib:
1099 handleSharedLibs(output);
1100 break;
1101 case DCcondition:
1102 case DCignore:
1103 // we are not interested in the output
1104 break;
1105 case DCinfothreads:
1106 handleThreadList(output);
1107 break;
1108 case DCsetpc:
1109 handleSetPC(output);
1110 break;
1111 case DCsetvariable:
1112 handleSetVariable(cmd, output);
1113 break;
1117 void KDebugger::backgroundUpdate()
1120 * If there are still expressions that need to be updated, then do so.
1122 if (m_programActive)
1123 evalExpressions();
1126 void KDebugger::handleRunCommands(const char* output)
1128 uint flags = m_d->parseProgramStopped(output, m_statusMessage);
1129 emit updateStatusMessage();
1131 m_programActive = flags & DebuggerDriver::SFprogramActive;
1133 // refresh files if necessary
1134 if (flags & DebuggerDriver::SFrefreshSource) {
1135 TRACE("re-reading files");
1136 emit executableUpdated();
1140 * Try to set any orphaned breakpoints now.
1142 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1143 if (m_brkpts[i]->isOrphaned()) {
1144 TRACE("re-trying brkpt loc: "+m_brkpts[i]->location+
1145 " file: "+m_brkpts[i]->fileName+
1146 QString().sprintf(" line: %d", m_brkpts[i]->lineNo));
1147 setBreakpoint(m_brkpts[i], true);
1148 flags |= DebuggerDriver::SFrefreshBreak;
1153 * If we stopped at a breakpoint, we must update the breakpoint list
1154 * because the hit count changes. Also, if the breakpoint was temporary
1155 * it would go away now.
1157 if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
1158 stopMayChangeBreakList())
1160 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
1164 * If we haven't listed the shared libraries yet, do so. We must do
1165 * this before we emit any commands that list variables, since the type
1166 * libraries depend on the shared libraries.
1168 if (!m_sharedLibsListed) {
1169 // must be a high-priority command!
1170 m_d->executeCmd(DCinfosharedlib);
1173 // get the backtrace if the program is running
1174 if (m_programActive) {
1175 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
1176 } else {
1177 // program finished: erase PC
1178 emit updatePC(QString(), -1, DbgAddr(), 0);
1179 // dequeue any commands in the queues
1180 m_d->flushCommands();
1183 /* Update threads list */
1184 if (m_programActive && (flags & DebuggerDriver::SFrefreshThreads)) {
1185 m_d->queueCmd(DCinfothreads, DebuggerDriver::QMoverride);
1188 m_programRunning = false;
1189 emit programStopped();
1192 void KDebugger::slotInferiorRunning()
1194 m_programRunning = true;
1197 void KDebugger::updateAllExprs()
1199 if (!m_programActive)
1200 return;
1202 // retrieve local variables
1203 m_d->queueCmd(DCinfolocals, DebuggerDriver::QMoverride);
1205 // retrieve registers
1206 m_d->queueCmd(DCinforegisters, DebuggerDriver::QMoverride);
1208 // get new memory dump
1209 if (!m_memoryExpression.isEmpty()) {
1210 queueMemoryDump(false);
1213 // update watch expressions
1214 KTreeViewItem* item = m_watchVariables.itemAt(0);
1215 for (; item != 0; item = item->getSibling()) {
1216 m_watchEvalExpr.append(static_cast<VarTree*>(item));
1220 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
1221 const QDict<EnvVar>& newVars,
1222 const QStringList& newOptions)
1224 m_programArgs = args;
1225 m_d->executeCmd(DCsetargs, m_programArgs);
1226 TRACE("new pgm args: " + m_programArgs + "\n");
1228 m_programWD = wd.stripWhiteSpace();
1229 if (!m_programWD.isEmpty()) {
1230 m_d->executeCmd(DCcd, m_programWD);
1231 TRACE("new wd: " + m_programWD + "\n");
1234 // update environment variables
1235 QDictIterator<EnvVar> it = newVars;
1236 EnvVar* val;
1237 for (; (val = it) != 0; ++it) {
1238 QString var = it.currentKey();
1239 switch (val->status) {
1240 case EnvVar::EVnew:
1241 m_envVars.insert(var, val);
1242 // fall thru
1243 case EnvVar::EVdirty:
1244 // the value must be in our list
1245 ASSERT(m_envVars[var] == val);
1246 // update value
1247 m_d->executeCmd(DCsetenv, var, val->value);
1248 break;
1249 case EnvVar::EVdeleted:
1250 // must be in our list
1251 ASSERT(m_envVars[var] == val);
1252 // delete value
1253 m_d->executeCmd(DCunsetenv, var);
1254 m_envVars.remove(var);
1255 break;
1256 default:
1257 ASSERT(false);
1258 case EnvVar::EVclean:
1259 // variable not changed
1260 break;
1264 // update options
1265 QStringList::ConstIterator oi;
1266 for (oi = newOptions.begin(); oi != newOptions.end(); ++oi)
1268 if (m_boolOptions.findIndex(*oi) < 0) {
1269 // the options is currently not set, so set it
1270 m_d->executeCmd(DCsetoption, *oi, 1);
1271 } else {
1272 // option is set, no action required, but move it to the end
1273 m_boolOptions.remove(*oi);
1275 m_boolOptions.append(*oi);
1278 * Now all options that should be set are at the end of m_boolOptions.
1279 * If some options need to be unset, they are at the front of the list.
1280 * Here we unset and remove them.
1282 while (m_boolOptions.count() > newOptions.count()) {
1283 m_d->executeCmd(DCsetoption, m_boolOptions.first(), 0);
1284 m_boolOptions.remove(m_boolOptions.begin());
1288 void KDebugger::handleLocals(const char* output)
1290 // retrieve old list of local variables
1291 QStrList oldVars;
1292 m_localVariables.exprList(oldVars);
1295 * Get local variables.
1297 QList<VarTree> newVars;
1298 parseLocals(output, newVars);
1301 * Clear any old VarTree item pointers, so that later we don't access
1302 * dangling pointers.
1304 m_localVariables.clearPendingUpdates();
1306 // reduce flicker
1307 bool autoU = m_localVariables.autoUpdate();
1308 m_localVariables.setAutoUpdate(false);
1309 bool repaintNeeded = false;
1312 * Match old variables against new ones.
1314 for (const char* n = oldVars.first(); n != 0; n = oldVars.next()) {
1315 // lookup this variable in the list of new variables
1316 VarTree* v = newVars.first();
1317 while (v != 0 && strcmp(v->getText(), n) != 0) {
1318 v = newVars.next();
1320 if (v == 0) {
1321 // old variable not in the new variables
1322 TRACE(QString("old var deleted: ") + n);
1323 v = m_localVariables.topLevelExprByName(n);
1324 if (v != 0) {
1325 m_localVariables.removeExpr(v);
1326 repaintNeeded = true;
1328 } else {
1329 // variable in both old and new lists: update
1330 TRACE(QString("update var: ") + n);
1331 m_localVariables.updateExpr(newVars.current());
1332 // remove the new variable from the list
1333 newVars.remove();
1334 delete v;
1335 repaintNeeded = true;
1338 // insert all remaining new variables
1339 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1340 TRACE("new var: " + v->getText());
1341 m_localVariables.insertExpr(v);
1342 repaintNeeded = true;
1345 // repaint
1346 m_localVariables.setAutoUpdate(autoU);
1347 if (repaintNeeded && autoU && m_localVariables.isVisible())
1348 m_localVariables.repaint();
1351 void KDebugger::parseLocals(const char* output, QList<VarTree>& newVars)
1353 QList<VarTree> vars;
1354 m_d->parseLocals(output, vars);
1356 QString origName; /* used in renaming variables */
1357 while (vars.count() > 0)
1359 VarTree* variable = vars.take(0);
1360 // get some types
1361 variable->inferTypesOfChildren(*m_typeTable);
1363 * When gdb prints local variables, those from the innermost block
1364 * come first. We run through the list of already parsed variables
1365 * to find duplicates (ie. variables that hide local variables from
1366 * a surrounding block). We keep the name of the inner variable, but
1367 * rename those from the outer block so that, when the value is
1368 * updated in the window, the value of the variable that is
1369 * _visible_ changes the color!
1371 int block = 0;
1372 origName = variable->getText();
1373 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1374 if (variable->getText() == v->getText()) {
1375 // we found a duplicate, change name
1376 block++;
1377 QString newName = origName + " (" + QString().setNum(block) + ")";
1378 variable->setText(newName);
1381 newVars.append(variable);
1385 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1387 ASSERT(cmd->m_expr != 0);
1389 VarTree* variable = parseExpr(output, true);
1390 if (variable == 0)
1391 return false;
1393 // set expression "name"
1394 variable->setText(cmd->m_expr->getText());
1397 TRACE("update expr: " + cmd->m_expr->getText());
1398 cmd->m_exprWnd->updateExpr(cmd->m_expr, variable);
1399 delete variable;
1402 evalExpressions(); /* enqueue dereferenced pointers */
1404 return true;
1407 bool KDebugger::handlePrintDeref(CmdQueueItem* cmd, const char* output)
1409 ASSERT(cmd->m_expr != 0);
1411 VarTree* variable = parseExpr(output, true);
1412 if (variable == 0)
1413 return false;
1415 // set expression "name"
1416 variable->setText(cmd->m_expr->getText());
1420 * We must insert a dummy parent, because otherwise variable's value
1421 * would overwrite cmd->m_expr's value.
1423 VarTree* dummyParent = new VarTree(variable->getText(), VarTree::NKplain);
1424 dummyParent->m_varKind = VarTree::VKdummy;
1425 // the name of the parsed variable is the address of the pointer
1426 QString addr = "*" + cmd->m_expr->m_value;
1427 variable->setText(addr);
1428 variable->m_nameKind = VarTree::NKaddress;
1430 dummyParent->appendChild(variable);
1431 // expand the first level for convenience
1432 variable->setExpanded(true);
1433 TRACE("update ptr: " + cmd->m_expr->getText());
1434 cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent);
1435 delete dummyParent;
1438 evalExpressions(); /* enqueue dereferenced pointers */
1440 return true;
1443 VarTree* KDebugger::parseExpr(const char* output, bool wantErrorValue)
1445 VarTree* variable;
1447 // check for error conditions
1448 bool goodValue = m_d->parsePrintExpr(output, wantErrorValue, variable);
1450 if (variable != 0 && goodValue)
1452 // get some types
1453 variable->inferTypesOfChildren(*m_typeTable);
1455 return variable;
1458 // parse the output of bt
1459 void KDebugger::handleBacktrace(const char* output)
1461 // reduce flicker
1462 m_btWindow.setAutoUpdate(false);
1464 m_btWindow.clear();
1466 QList<StackFrame> stack;
1467 m_d->parseBackTrace(output, stack);
1469 if (stack.count() > 0) {
1470 StackFrame* frm = stack.take(0);
1471 // first frame must set PC
1472 // note: frm->lineNo is zero-based
1473 emit updatePC(frm->fileName, frm->lineNo, frm->address, frm->frameNo);
1475 do {
1476 QString func;
1477 if (frm->var != 0)
1478 func = frm->var->getText();
1479 else
1480 func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1481 m_btWindow.insertItem(func);
1482 TRACE("frame " + func + " (" + frm->fileName + ":" +
1483 QString().setNum(frm->lineNo+1) + ")");
1484 delete frm;
1486 while ((frm = stack.take()) != 0);
1489 m_btWindow.setAutoUpdate(true);
1490 m_btWindow.repaint();
1493 void KDebugger::gotoFrame(int frame)
1495 m_d->executeCmd(DCframe, frame);
1498 void KDebugger::handleFrameChange(const char* output)
1500 QString fileName;
1501 int frameNo;
1502 int lineNo;
1503 DbgAddr address;
1504 if (m_d->parseFrameChange(output, frameNo, fileName, lineNo, address)) {
1505 /* lineNo can be negative here if we can't find a file name */
1506 emit updatePC(fileName, lineNo, address, frameNo);
1507 } else {
1508 emit updatePC(fileName, -1, address, frameNo);
1512 void KDebugger::evalExpressions()
1514 // evaluate expressions in the following order:
1515 // watch expressions
1516 // pointers in local variables
1517 // pointers in watch expressions
1518 // types in local variables
1519 // types in watch expressions
1520 // pointers in 'this'
1521 // types in 'this'
1523 VarTree* exprItem = m_watchEvalExpr.first();
1524 if (exprItem != 0) {
1525 m_watchEvalExpr.remove();
1526 QString expr = exprItem->computeExpr();
1527 TRACE("watch expr: " + expr);
1528 CmdQueueItem* cmd = m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverride);
1529 // remember which expr this was
1530 cmd->m_expr = exprItem;
1531 cmd->m_exprWnd = &m_watchVariables;
1532 } else {
1533 ExprWnd* wnd;
1534 VarTree* exprItem;
1535 #define POINTER(widget) \
1536 wnd = &widget; \
1537 exprItem = widget.nextUpdatePtr(); \
1538 if (exprItem != 0) goto pointer
1539 #define STRUCT(widget) \
1540 wnd = &widget; \
1541 exprItem = widget.nextUpdateStruct(); \
1542 if (exprItem != 0) goto ustruct
1543 #define TYPE(widget) \
1544 wnd = &widget; \
1545 exprItem = widget.nextUpdateType(); \
1546 if (exprItem != 0) goto type
1547 repeat:
1548 POINTER(m_localVariables);
1549 POINTER(m_watchVariables);
1550 STRUCT(m_localVariables);
1551 STRUCT(m_watchVariables);
1552 TYPE(m_localVariables);
1553 TYPE(m_watchVariables);
1554 #undef POINTER
1555 #undef STRUCT
1556 #undef TYPE
1557 return;
1559 pointer:
1560 // we have an expression to send
1561 dereferencePointer(wnd, exprItem, false);
1562 return;
1564 ustruct:
1565 // paranoia
1566 if (exprItem->m_type == 0 || exprItem->m_type == TypeInfo::unknownType())
1567 goto repeat;
1568 evalInitialStructExpression(exprItem, wnd, false);
1569 return;
1571 type:
1573 * Sometimes a VarTree gets registered twice for a type update. So
1574 * it may happen that it has already been updated. Hence, we ignore
1575 * it here and go on to the next task.
1577 if (exprItem->m_type != 0)
1578 goto repeat;
1579 determineType(wnd, exprItem);
1583 void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem,
1584 bool immediate)
1586 ASSERT(exprItem->m_varKind == VarTree::VKpointer);
1588 QString expr = exprItem->computeExpr();
1589 TRACE("dereferencing pointer: " + expr);
1590 CmdQueueItem* cmd;
1591 if (immediate) {
1592 cmd = m_d->queueCmd(DCprintDeref, expr, DebuggerDriver::QMoverrideMoreEqual);
1593 } else {
1594 cmd = m_d->queueCmd(DCprintDeref, expr, DebuggerDriver::QMoverride);
1596 // remember which expr this was
1597 cmd->m_expr = exprItem;
1598 cmd->m_exprWnd = wnd;
1601 void KDebugger::determineType(ExprWnd* wnd, VarTree* exprItem)
1603 ASSERT(exprItem->m_varKind == VarTree::VKstruct);
1605 QString expr = exprItem->computeExpr();
1606 TRACE("get type of: " + expr);
1607 CmdQueueItem* cmd;
1608 cmd = m_d->queueCmd(DCfindType, expr, DebuggerDriver::QMoverride);
1610 // remember which expr this was
1611 cmd->m_expr = exprItem;
1612 cmd->m_exprWnd = wnd;
1615 void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output)
1617 QString type;
1618 if (m_d->parseFindType(output, type))
1620 ASSERT(cmd != 0 && cmd->m_expr != 0);
1622 TypeInfo* info = m_typeTable->lookup(type);
1624 if (info == 0) {
1626 * We've asked gdb for the type of the expression in
1627 * cmd->m_expr, but it returned a name we don't know. The base
1628 * class (and member) types have been checked already (at the
1629 * time when we parsed that particular expression). Now it's
1630 * time to derive the type from the base classes as a last
1631 * resort.
1633 info = cmd->m_expr->inferTypeFromBaseClass();
1634 // if we found a type through this method, register an alias
1635 if (info != 0) {
1636 TRACE("infered alias: " + type);
1637 m_typeTable->registerAlias(type, info);
1640 if (info == 0) {
1641 TRACE("unknown type "+type);
1642 cmd->m_expr->m_type = TypeInfo::unknownType();
1643 } else {
1644 cmd->m_expr->m_type = info;
1645 /* since this node has a new type, we get its value immediately */
1646 evalInitialStructExpression(cmd->m_expr, cmd->m_exprWnd, false);
1647 return;
1651 evalExpressions(); /* queue more of them */
1654 void KDebugger::handlePrintStruct(CmdQueueItem* cmd, const char* output)
1656 VarTree* var = cmd->m_expr;
1657 ASSERT(var != 0);
1658 ASSERT(var->m_varKind == VarTree::VKstruct);
1660 VarTree* partExpr;
1661 if (cmd->m_cmd == DCprintQStringStruct) {
1662 partExpr = m_d->parseQCharArray(output, false, m_typeTable->qCharIsShort());
1663 } else if (cmd->m_cmd == DCprintWChar) {
1664 partExpr = m_d->parseQCharArray(output, false, true);
1665 } else {
1666 partExpr = parseExpr(output, false);
1668 bool errorValue =
1669 partExpr == 0 ||
1670 /* we only allow simple values at the moment */
1671 partExpr->childCount() != 0;
1673 QString partValue;
1674 if (errorValue)
1676 partValue = "?""?""?"; // 2 question marks in a row would be a trigraph
1677 } else {
1678 partValue = partExpr->m_value;
1680 delete partExpr;
1681 partExpr = 0;
1684 * Updating a struct value works like this: var->m_partialValue holds
1685 * the value that we have gathered so far (it's been initialized with
1686 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1687 * we append the printed result followed by the next
1688 * var->m_type->m_displayString to var->m_partialValue.
1690 * If the expression we just evaluated was a guard expression, and it
1691 * resulted in an error, we must not evaluate the real expression, but
1692 * go on to the next index. (We must still add the question marks to
1693 * the value).
1695 * Next, if this was the length expression, we still have not seen the
1696 * real expression, but the length of a QString.
1698 ASSERT(var->m_exprIndex >= 0 && var->m_exprIndex <= typeInfoMaxExpr);
1700 if (errorValue || !var->m_exprIndexUseGuard)
1702 // add current partValue (which might be the question marks)
1703 var->m_partialValue += partValue;
1704 var->m_exprIndex++; /* next part */
1705 var->m_exprIndexUseGuard = true;
1706 var->m_partialValue += var->m_type->m_displayString[var->m_exprIndex];
1708 else
1710 // this was a guard expression that succeeded
1711 // go for the real expression
1712 var->m_exprIndexUseGuard = false;
1715 /* go for more sub-expressions if needed */
1716 if (var->m_exprIndex < var->m_type->m_numExprs) {
1717 /* queue a new print command with quite high priority */
1718 evalStructExpression(var, cmd->m_exprWnd, true);
1719 return;
1722 cmd->m_exprWnd->updateStructValue(var);
1724 evalExpressions(); /* enqueue dereferenced pointers */
1727 /* queues the first printStruct command for a struct */
1728 void KDebugger::evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1730 var->m_exprIndex = 0;
1731 if (var->m_type != TypeInfo::wchartType())
1733 var->m_exprIndexUseGuard = true;
1734 var->m_partialValue = var->m_type->m_displayString[0];
1735 evalStructExpression(var, wnd, immediate);
1737 else
1739 var->m_exprIndexUseGuard = false;
1740 QString expr = var->computeExpr();
1741 CmdQueueItem* cmd = m_d->queueCmd(DCprintWChar, expr,
1742 immediate ? DebuggerDriver::QMoverrideMoreEqual
1743 : DebuggerDriver::QMoverride);
1744 // remember which expression this was
1745 cmd->m_expr = var;
1746 cmd->m_exprWnd = wnd;
1750 /* queues a printStruct command; var must have been initialized correctly */
1751 void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1753 QString base = var->computeExpr();
1754 QString exprFmt;
1755 if (var->m_exprIndexUseGuard) {
1756 exprFmt = var->m_type->m_guardStrings[var->m_exprIndex];
1757 if (exprFmt.isEmpty()) {
1758 // no guard, omit it and go to expression
1759 var->m_exprIndexUseGuard = false;
1762 if (!var->m_exprIndexUseGuard) {
1763 exprFmt = var->m_type->m_exprStrings[var->m_exprIndex];
1766 QString expr;
1767 expr.sprintf(exprFmt, base.data());
1769 DbgCommand dbgCmd = DCprintStruct;
1770 // check if this is a QString::Data
1771 if (strncmp(expr, "/QString::Data ", 15) == 0)
1773 if (m_typeTable->parseQt2QStrings())
1775 expr = expr.mid(15, expr.length()); /* strip off /QString::Data */
1776 dbgCmd = DCprintQStringStruct;
1777 } else {
1779 * This should not happen: the type libraries should be set up
1780 * in a way that this can't happen. If this happens
1781 * nevertheless it means that, eg., kdecore was loaded but qt2
1782 * was not (only qt2 enables the QString feature).
1784 // TODO: remove this "print"; queue the next printStruct instead
1785 expr = "*0";
1787 } else {
1788 expr = expr;
1790 TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1791 CmdQueueItem* cmd = m_d->queueCmd(dbgCmd, expr,
1792 immediate ? DebuggerDriver::QMoverrideMoreEqual
1793 : DebuggerDriver::QMnormal);
1795 // remember which expression this was
1796 cmd->m_expr = var;
1797 cmd->m_exprWnd = wnd;
1800 void KDebugger::handleSharedLibs(const char* output)
1802 // delete all known libraries
1803 m_sharedLibs.clear();
1805 // parse the table of shared libraries
1806 m_d->parseSharedLibs(output, m_sharedLibs);
1807 m_sharedLibsListed = true;
1809 // get type libraries
1810 m_typeTable->loadLibTypes(m_sharedLibs);
1812 // hand over the QString data cmd
1813 m_d->setPrintQStringDataCmd(m_typeTable->printQStringDataCmd());
1816 CmdQueueItem* KDebugger::loadCoreFile()
1818 return m_d->queueCmd(DCcorefile, m_corefile, DebuggerDriver::QMoverride);
1821 void KDebugger::slotLocalsExpanding(KTreeViewItem* item, bool& allow)
1823 exprExpandingHelper(&m_localVariables, item, allow);
1826 void KDebugger::slotWatchExpanding(KTreeViewItem* item, bool& allow)
1828 exprExpandingHelper(&m_watchVariables, item, allow);
1831 void KDebugger::exprExpandingHelper(ExprWnd* wnd, KTreeViewItem* item, bool&)
1833 VarTree* exprItem = static_cast<VarTree*>(item);
1834 if (exprItem->m_varKind != VarTree::VKpointer) {
1835 return;
1837 dereferencePointer(wnd, exprItem, true);
1840 // add the expression in the edit field to the watch expressions
1841 void KDebugger::addWatch(const QString& t)
1843 QString expr = t.stripWhiteSpace();
1844 if (expr.isEmpty())
1845 return;
1846 VarTree* exprItem = new VarTree(expr, VarTree::NKplain);
1847 m_watchVariables.insertExpr(exprItem);
1849 // if we are boring ourselves, send down the command
1850 if (m_programActive) {
1851 m_watchEvalExpr.append(exprItem);
1852 if (m_d->isIdle()) {
1853 evalExpressions();
1858 // delete a toplevel watch expression
1859 void KDebugger::slotDeleteWatch()
1861 // delete only allowed while debugger is idle; or else we might delete
1862 // the very expression the debugger is currently working on...
1863 if (!m_d->isIdle())
1864 return;
1866 int index = m_watchVariables.currentItem();
1867 if (index < 0)
1868 return;
1870 VarTree* item = static_cast<VarTree*>(m_watchVariables.itemAt(index));
1871 if (!item->isToplevelExpr())
1872 return;
1874 // remove the variable from the list to evaluate
1875 if (m_watchEvalExpr.findRef(item) >= 0) {
1876 m_watchEvalExpr.remove();
1878 m_watchVariables.removeExpr(item);
1879 // item is invalid at this point!
1882 void KDebugger::handleRegisters(const char* output)
1884 QList<RegisterInfo> regs;
1885 m_d->parseRegisters(output, regs);
1887 emit registersChanged(regs);
1889 // delete them all
1890 regs.setAutoDelete(true);
1894 * The output of the DCbreak* commands has more accurate information about
1895 * the file and the line number.
1897 * All newly set breakpoints are inserted in the m_brkpts, even those that
1898 * were not set sucessfully. The unsuccessful breakpoints ("orphaned
1899 * breakpoints") are assigned negative ids, and they are tried to set later
1900 * when the program stops again at a breakpoint.
1902 void KDebugger::newBreakpoint(CmdQueueItem* cmd, const char* output)
1904 Breakpoint* bp = cmd->m_brkpt;
1905 assert(bp != 0);
1906 if (bp == 0)
1907 return;
1909 // if this is a new breakpoint, put it in the list
1910 bool isNew = !m_brkpts.contains(bp);
1911 if (isNew) {
1912 assert(bp->id == 0);
1913 int n = m_brkpts.size();
1914 m_brkpts.resize(n+1);
1915 m_brkpts.insert(n, bp);
1918 // parse the output to determine success or failure
1919 int id;
1920 QString file;
1921 int lineNo;
1922 QString address;
1923 if (!m_d->parseBreakpoint(output, id, file, lineNo, address))
1926 * Failure, the breakpoint could not be set. If this is a new
1927 * breakpoint, assign it a negative id. We look for the minimal id
1928 * of all breakpoints (that are already in the list) to get the new
1929 * id.
1931 if (isNew)
1933 assert(bp->id == 0);
1934 for (int i = m_brkpts.size()-2; i >= 0; i--) {
1935 if (m_brkpts[i]->id < bp->id) {
1936 bp->id = m_brkpts[i]->id;
1937 break;
1940 --bp->id;
1942 return;
1945 // The breakpoint was successfully set.
1946 if (bp->id <= 0)
1948 // this is a new or orphaned breakpoint:
1949 // set the remaining properties
1950 if (!cmd->m_brkpt->enabled) {
1951 m_d->executeCmd(DCdisable, id);
1953 if (!cmd->m_brkpt->condition.isEmpty()) {
1954 m_d->executeCmd(DCcondition, cmd->m_brkpt->condition, id);
1958 bp->id = id;
1959 bp->fileName = file;
1960 bp->lineNo = lineNo;
1961 if (!address.isEmpty())
1962 bp->address = address;
1965 void KDebugger::updateBreakList(const char* output)
1967 // get the new list
1968 QList<Breakpoint> brks;
1969 brks.setAutoDelete(false);
1970 m_d->parseBreakList(output, brks);
1972 // merge new information into existing breakpoints
1974 for (int i = m_brkpts.size()-1; i >= 0; i--) // decrement!
1976 // skip orphaned breakpoints
1977 if (m_brkpts[i]->id < 0)
1978 continue;
1980 for (Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
1982 if (bp->id == m_brkpts[i]->id) {
1983 // keep accurate location
1984 // except that xsldbg doesn't have a location in
1985 // the old breakpoint if it's just been set
1986 bp->text = m_brkpts[i]->text;
1987 if (!m_brkpts[i]->fileName.isEmpty()) {
1988 bp->fileName = m_brkpts[i]->fileName;
1989 bp->lineNo = m_brkpts[i]->lineNo;
1991 m_brkpts.insert(i, bp); // old object is deleted
1992 goto stillAlive;
1996 * If we get here, this breakpoint is no longer present.
1998 * To delete the breakpoint at i, we place the last breakpoint in
1999 * the list into the slot i. This will delete the old object at i.
2000 * Then we shorten the list by one.
2002 m_brkpts.insert(i, m_brkpts.take(m_brkpts.size()-1));
2003 m_brkpts.resize(m_brkpts.size()-1);
2004 TRACE(QString().sprintf("deleted brkpt %d, have now %d brkpts", i, m_brkpts.size()));
2006 stillAlive:;
2009 // brks may contain new breakpoints not already in m_brkpts
2010 for (const Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
2012 bool found = false;
2013 for (uint i = 0; i < m_brkpts.size(); i++) {
2014 if (bp->id == m_brkpts[i]->id) {
2015 found = true;
2016 break;
2019 if (!found){
2020 int n = m_brkpts.size();
2021 m_brkpts.resize(n+1);
2022 m_brkpts.insert(n, bp);
2026 emit breakpointsChanged();
2029 // look if there is at least one temporary breakpoint
2030 // or a watchpoint
2031 bool KDebugger::stopMayChangeBreakList() const
2033 for (int i = m_brkpts.size()-1; i >= 0; i--) {
2034 Breakpoint* bp = m_brkpts[i];
2035 if (bp->temporary || bp->type == Breakpoint::watchpoint)
2036 return true;
2038 return false;
2041 Breakpoint* KDebugger::breakpointByFilePos(QString file, int lineNo,
2042 const DbgAddr& address)
2044 // look for exact file name match
2045 int i;
2046 for (i = m_brkpts.size()-1; i >= 0; i--) {
2047 if (m_brkpts[i]->lineNo == lineNo &&
2048 m_brkpts[i]->fileName == file &&
2049 (address.isEmpty() || m_brkpts[i]->address == address))
2051 return m_brkpts[i];
2054 // not found, so try basename
2055 // strip off directory part of file name
2056 int offset = file.findRev("/");
2057 file.remove(0, offset+1);
2059 for (i = m_brkpts.size()-1; i >= 0; i--) {
2060 // get base name of breakpoint's file
2061 QString basename = m_brkpts[i]->fileName;
2062 int offset = basename.findRev("/");
2063 if (offset >= 0) {
2064 basename.remove(0, offset+1);
2067 if (m_brkpts[i]->lineNo == lineNo &&
2068 basename == file &&
2069 (address.isEmpty() || m_brkpts[i]->address == address))
2071 return m_brkpts[i];
2075 // not found
2076 return 0;
2079 Breakpoint* KDebugger::breakpointById(int id)
2081 for (int i = m_brkpts.size()-1; i >= 0; i--)
2083 if (m_brkpts[i]->id == id) {
2084 return m_brkpts[i];
2087 // not found
2088 return 0;
2091 void KDebugger::slotValuePopup(const QString& expr)
2093 // search the local variables for a match
2094 VarTree* v = m_localVariables.topLevelExprByName(expr);
2095 if (v == 0) {
2096 // not found, check watch expressions
2097 v = m_watchVariables.topLevelExprByName(expr);
2098 if (v == 0) {
2099 // try a member of 'this'
2100 v = m_localVariables.topLevelExprByName("this");
2101 if (v != 0)
2102 v = ExprWnd::ptrMemberByName(v, expr);
2103 if (v == 0) {
2104 // nothing found; do nothing
2105 return;
2110 // construct the tip
2111 QString tip = v->getText() + " = ";
2112 if (!v->m_value.isEmpty())
2114 tip += v->m_value;
2116 else
2118 // no value: we use some hint
2119 switch (v->m_varKind) {
2120 case VarTree::VKstruct:
2121 tip += "{...}";
2122 break;
2123 case VarTree::VKarray:
2124 tip += "[...]";
2125 break;
2126 default:
2127 tip += "?""?""?"; // 2 question marks in a row would be a trigraph
2128 break;
2131 emit valuePopup(tip);
2134 void KDebugger::slotDisassemble(const QString& fileName, int lineNo)
2136 CmdQueueItem* cmd = m_d->queueCmd(DCinfoline, fileName, lineNo,
2137 DebuggerDriver::QMoverrideMoreEqual);
2138 cmd->m_fileName = fileName;
2139 cmd->m_lineNo = lineNo;
2142 void KDebugger::handleInfoLine(CmdQueueItem* cmd, const char* output)
2144 QString addrFrom, addrTo;
2145 if (cmd->m_lineNo >= 0) {
2146 // disassemble
2147 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2148 // got the address range, now get the real code
2149 CmdQueueItem* c = m_d->queueCmd(DCdisassemble, addrFrom, addrTo,
2150 DebuggerDriver::QMoverrideMoreEqual);
2151 c->m_fileName = cmd->m_fileName;
2152 c->m_lineNo = cmd->m_lineNo;
2153 } else {
2154 // no code
2155 QList<DisassembledCode> empty;
2156 emit disassembled(cmd->m_fileName, cmd->m_lineNo, empty);
2158 } else {
2159 // set program counter
2160 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2161 // move the program counter to the start address
2162 m_d->executeCmd(DCsetpc, addrFrom);
2167 void KDebugger::handleDisassemble(CmdQueueItem* cmd, const char* output)
2169 QList<DisassembledCode> code;
2170 code.setAutoDelete(true);
2171 m_d->parseDisassemble(output, code);
2172 emit disassembled(cmd->m_fileName, cmd->m_lineNo, code);
2175 void KDebugger::handleThreadList(const char* output)
2177 QList<ThreadInfo> threads;
2178 threads.setAutoDelete(true);
2179 m_d->parseThreadList(output, threads);
2180 emit threadsChanged(threads);
2183 void KDebugger::setThread(int id)
2185 m_d->queueCmd(DCthread, id, DebuggerDriver::QMoverrideMoreEqual);
2188 void KDebugger::setMemoryExpression(const QString& memexpr)
2190 m_memoryExpression = memexpr;
2192 // queue the new expression
2193 if (!m_memoryExpression.isEmpty() &&
2194 isProgramActive() &&
2195 !isProgramRunning())
2197 queueMemoryDump(true);
2201 void KDebugger::queueMemoryDump(bool immediate)
2203 m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat,
2204 immediate ? DebuggerDriver::QMoverrideMoreEqual :
2205 DebuggerDriver::QMoverride);
2208 void KDebugger::handleMemoryDump(const char* output)
2210 QList<MemoryDump> memdump;
2211 memdump.setAutoDelete(true);
2212 QString msg = m_d->parseMemoryDump(output, memdump);
2213 emit memoryDumpChanged(msg, memdump);
2216 void KDebugger::setProgramCounter(const QString& file, int line, const DbgAddr& addr)
2218 if (addr.isEmpty()) {
2219 // find address of the specified line
2220 CmdQueueItem* cmd = m_d->executeCmd(DCinfoline, file, line);
2221 cmd->m_lineNo = -1; /* indicates "Set PC" UI command */
2222 } else {
2223 // move the program counter to that address
2224 m_d->executeCmd(DCsetpc, addr.asString());
2228 void KDebugger::handleSetPC(const char* /*output*/)
2230 // TODO: handle errors
2232 // now go to the top-most frame
2233 // this also modifies the program counter indicator in the UI
2234 gotoFrame(0);
2237 void KDebugger::slotValueEdited(int row, const QString& text)
2239 if (text.simplifyWhiteSpace().isEmpty())
2240 return; /* no text entered: ignore request */
2242 ASSERT(sender()->inherits("ExprWnd"));
2243 ExprWnd* wnd = const_cast<ExprWnd*>(static_cast<const ExprWnd*>(sender()));
2244 TRACE(QString().sprintf("Changing %s at row %d to ",
2245 wnd->name(), row) + text);
2247 // determine the lvalue to edit
2248 VarTree* expr = static_cast<VarTree*>(wnd->itemAt(row));
2249 QString lvalue = expr->computeExpr();
2250 CmdQueueItem* cmd = m_d->executeCmd(DCsetvariable, lvalue, text);
2251 cmd->m_expr = expr;
2252 cmd->m_exprWnd = wnd;
2255 void KDebugger::handleSetVariable(CmdQueueItem* cmd, const char* output)
2257 QString msg = m_d->parseSetVariable(output);
2258 if (!msg.isEmpty())
2260 // there was an error; display it in the status bar
2261 m_statusMessage = msg;
2262 emit updateStatusMessage();
2263 return;
2266 // get the new value
2267 QString expr = cmd->m_expr->computeExpr();
2268 CmdQueueItem* printCmd =
2269 m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverrideMoreEqual);
2270 printCmd->m_expr = cmd->m_expr;
2271 printCmd->m_exprWnd = cmd->m_exprWnd;
2275 #include "debugger.moc"