Convert from Qt 3 to Qt 4 using qt3to4.
[kdbg.git] / kdbg / debugger.cpp
blobb83afce23ac2e991416f4f550a0362338c4449ee
1 /*
2 * Copyright Johannes Sixt
3 * This file is licensed under the GNU General Public License Version 2.
4 * See the file COPYING in the toplevel directory of the source directory.
5 */
7 #include "debugger.h"
8 #include "dbgdriver.h"
9 #include "pgmargs.h"
10 #include "typetable.h"
11 #include "exprwnd.h"
12 #include "pgmsettings.h"
13 #include <qregexp.h>
14 #include <qfileinfo.h>
15 #include <q3listbox.h>
16 #include <qstringlist.h>
17 #include <kapplication.h>
18 #include <kconfig.h>
19 #include <klocale.h> /* i18n */
20 #include <kmessagebox.h>
21 #include <kconfig.h>
22 #include <ctype.h>
23 #include <stdlib.h> /* strtol, atoi */
24 #include <unistd.h> /* sleep(3) */
25 #include "mydebug.h"
28 KDebugger::KDebugger(QWidget* parent,
29 ExprWnd* localVars,
30 ExprWnd* watchVars,
31 Q3ListBox* backtrace) :
32 QObject(parent, "debugger"),
33 m_ttyLevel(ttyFull),
34 m_memoryFormat(MDTword | MDThex),
35 m_haveExecutable(false),
36 m_programActive(false),
37 m_programRunning(false),
38 m_sharedLibsListed(false),
39 m_typeTable(0),
40 m_programConfig(0),
41 m_d(0),
42 m_localVariables(*localVars),
43 m_watchVariables(*watchVars),
44 m_btWindow(*backtrace)
46 m_envVars.setAutoDelete(true);
48 connect(&m_localVariables, SIGNAL(expanded(Q3ListViewItem*)),
49 SLOT(slotExpanding(Q3ListViewItem*)));
50 connect(&m_watchVariables, SIGNAL(expanded(Q3ListViewItem*)),
51 SLOT(slotExpanding(Q3ListViewItem*)));
52 connect(&m_localVariables, SIGNAL(editValueCommitted(VarTree*, const QString&)),
53 SLOT(slotValueEdited(VarTree*, const QString&)));
54 connect(&m_watchVariables, SIGNAL(editValueCommitted(VarTree*, const QString&)),
55 SLOT(slotValueEdited(VarTree*, const QString&)));
57 connect(&m_btWindow, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
59 emit updateUI();
62 KDebugger::~KDebugger()
64 if (m_programConfig != 0) {
65 saveProgramSettings();
66 m_programConfig->sync();
67 delete m_programConfig;
70 delete m_typeTable;
74 void KDebugger::saveSettings(KConfig* /*config*/)
78 void KDebugger::restoreSettings(KConfig* /*config*/)
83 //////////////////////////////////////////////////////////////////////
84 // external interface
86 const char GeneralGroup[] = "General";
87 const char DebuggerCmdStr[] = "DebuggerCmdStr";
88 const char TTYLevelEntry[] = "TTYLevel";
89 const char KDebugger::DriverNameEntry[] = "DriverName";
91 bool KDebugger::debugProgram(const QString& name,
92 DebuggerDriver* driver)
94 if (m_d != 0 && m_d->isRunning())
96 QApplication::setOverrideCursor(Qt::waitCursor);
98 stopDriver();
100 QApplication::restoreOverrideCursor();
102 if (m_d->isRunning() || m_haveExecutable) {
103 /* timed out! We can't really do anything useful now */
104 TRACE("timed out while waiting for gdb to die!");
105 return false;
107 delete m_d;
108 m_d = 0;
111 // wire up the driver
112 connect(driver, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
113 this, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)));
114 connect(driver, SIGNAL(processExited(KProcess*)), SLOT(gdbExited(KProcess*)));
115 connect(driver, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
116 SLOT(parse(CmdQueueItem*,const char*)));
117 connect(driver, SIGNAL(wroteStdin(KProcess*)), SIGNAL(updateUI()));
118 connect(driver, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
119 connect(driver, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
120 connect(driver, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
121 connect(&m_localVariables, SIGNAL(removingItem(VarTree*)),
122 driver, SLOT(dequeueCmdByVar(VarTree*)));
123 connect(&m_watchVariables, SIGNAL(removingItem(VarTree*)),
124 driver, SLOT(dequeueCmdByVar(VarTree*)));
126 // create the program settings object
127 openProgramConfig(name);
129 // get debugger command from per-program settings
130 if (m_programConfig != 0) {
131 m_programConfig->setGroup(GeneralGroup);
132 m_debuggerCmd = readDebuggerCmd();
133 // get terminal emulation level
134 m_ttyLevel = TTYLevel(m_programConfig->readNumEntry(TTYLevelEntry, ttyFull));
136 // the rest is read in later in the handler of DCexecutable
138 m_d = driver;
140 if (!startDriver()) {
141 TRACE("startDriver failed");
142 m_d = 0;
143 return false;
146 TRACE("before file cmd");
147 m_d->executeCmd(DCexecutable, name);
148 m_executable = name;
150 // set remote target
151 if (!m_remoteDevice.isEmpty()) {
152 m_d->executeCmd(DCtargetremote, m_remoteDevice);
153 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
154 m_d->queueCmd(DCframe, 0, DebuggerDriver::QMnormal);
155 m_programActive = true;
156 m_haveExecutable = true;
159 // create a type table
160 m_typeTable = new ProgramTypeTable;
161 m_sharedLibsListed = false;
163 emit updateUI();
165 return true;
168 void KDebugger::shutdown()
170 // shut down debugger driver
171 if (m_d != 0 && m_d->isRunning())
173 stopDriver();
177 void KDebugger::useCoreFile(QString corefile, bool batch)
179 m_corefile = corefile;
180 if (!batch) {
181 CmdQueueItem* cmd = loadCoreFile();
182 cmd->m_byUser = true;
186 void KDebugger::setAttachPid(const QString& pid)
188 m_attachedPid = pid;
191 void KDebugger::programRun()
193 if (!isReady())
194 return;
196 // when program is active, but not a core file, continue
197 // otherwise run the program
198 if (m_programActive && m_corefile.isEmpty()) {
199 // gdb command: continue
200 m_d->executeCmd(DCcont, true);
201 } else {
202 // gdb command: run
203 m_d->executeCmd(DCrun, true);
204 m_corefile = QString();
205 m_programActive = true;
207 m_programRunning = true;
210 void KDebugger::attachProgram(const QString& pid)
212 if (!isReady())
213 return;
215 m_attachedPid = pid;
216 TRACE("Attaching to " + m_attachedPid);
217 m_d->executeCmd(DCattach, m_attachedPid);
218 m_programActive = true;
219 m_programRunning = true;
222 void KDebugger::programRunAgain()
224 if (canSingleStep()) {
225 m_d->executeCmd(DCrun, true);
226 m_corefile = QString();
227 m_programRunning = true;
231 void KDebugger::programStep()
233 if (canSingleStep()) {
234 m_d->executeCmd(DCstep, true);
235 m_programRunning = true;
239 void KDebugger::programNext()
241 if (canSingleStep()) {
242 m_d->executeCmd(DCnext, true);
243 m_programRunning = true;
247 void KDebugger::programStepi()
249 if (canSingleStep()) {
250 m_d->executeCmd(DCstepi, true);
251 m_programRunning = true;
255 void KDebugger::programNexti()
257 if (canSingleStep()) {
258 m_d->executeCmd(DCnexti, true);
259 m_programRunning = true;
263 void KDebugger::programFinish()
265 if (canSingleStep()) {
266 m_d->executeCmd(DCfinish, true);
267 m_programRunning = true;
271 void KDebugger::programKill()
273 if (haveExecutable() && isProgramActive()) {
274 if (m_programRunning) {
275 m_d->interruptInferior();
277 // this is an emergency command; flush queues
278 m_d->flushCommands(true);
279 m_d->executeCmd(DCkill, true);
283 bool KDebugger::runUntil(const QString& fileName, int lineNo)
285 if (isReady() && m_programActive && !m_programRunning) {
286 // strip off directory part of file name
287 QString file = fileName;
288 int offset = file.findRev("/");
289 if (offset >= 0) {
290 file.remove(0, offset+1);
292 m_d->executeCmd(DCuntil, file, lineNo, true);
293 m_programRunning = true;
294 return true;
295 } else {
296 return false;
300 void KDebugger::programBreak()
302 if (m_haveExecutable && m_programRunning) {
303 m_d->interruptInferior();
307 void KDebugger::programArgs(QWidget* parent)
309 if (m_haveExecutable) {
310 QStringList allOptions = m_d->boolOptionList();
311 PgmArgs dlg(parent, m_executable, m_envVars, allOptions);
312 dlg.setArgs(m_programArgs);
313 dlg.setWd(m_programWD);
314 dlg.setOptions(m_boolOptions);
315 if (dlg.exec()) {
316 updateProgEnvironment(dlg.args(), dlg.wd(),
317 dlg.envVars(), dlg.options());
322 void KDebugger::programSettings(QWidget* parent)
324 if (!m_haveExecutable)
325 return;
327 ProgramSettings dlg(parent, m_executable);
329 dlg.m_chooseDriver.setDebuggerCmd(m_debuggerCmd);
330 dlg.m_output.setTTYLevel(m_ttyLevel);
332 if (dlg.exec() == QDialog::Accepted)
334 m_debuggerCmd = dlg.m_chooseDriver.debuggerCmd();
335 m_ttyLevel = TTYLevel(dlg.m_output.ttyLevel());
339 bool KDebugger::setBreakpoint(QString file, int lineNo,
340 const DbgAddr& address, bool temporary)
342 if (!isReady()) {
343 return false;
346 BrkptIterator bp = breakpointByFilePos(file, lineNo, address);
347 if (bp == m_brkpts.end())
350 * No such breakpoint, so set a new one. If we have an address, we
351 * set the breakpoint exactly there. Otherwise we use the file name
352 * plus line no.
354 Breakpoint* bp = new Breakpoint;
355 bp->temporary = temporary;
357 if (address.isEmpty())
359 bp->fileName = file;
360 bp->lineNo = lineNo;
362 else
364 bp->address = address;
366 setBreakpoint(bp, false);
368 else
371 * If the breakpoint is disabled, enable it; if it's enabled,
372 * delete that breakpoint.
374 if (bp->enabled) {
375 deleteBreakpoint(bp);
376 } else {
377 enableDisableBreakpoint(bp);
380 return true;
383 void KDebugger::setBreakpoint(Breakpoint* bp, bool queueOnly)
385 CmdQueueItem* cmd = executeBreakpoint(bp, queueOnly);
386 cmd->m_brkpt = bp; // used in newBreakpoint()
389 CmdQueueItem* KDebugger::executeBreakpoint(const 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 return cmd;
433 bool KDebugger::infoLine(QString file, int lineNo, const DbgAddr& addr)
435 if (isReady() && !m_programRunning) {
436 CmdQueueItem* cmd = m_d->executeCmd(DCinfoline, file, lineNo);
437 cmd->m_addr = addr;
438 return true;
439 } else {
440 return false;
444 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo,
445 const DbgAddr& address)
447 BrkptIterator bp = breakpointByFilePos(file, lineNo, address);
448 return enableDisableBreakpoint(bp);
451 bool KDebugger::enableDisableBreakpoint(BrkptIterator bp)
453 if (bp == m_brkpts.end())
454 return false;
457 * Toggle enabled/disabled state.
459 * The driver is not bothered if we are modifying an orphaned
460 * breakpoint.
462 if (!bp->isOrphaned()) {
463 if (!canChangeBreakpoints()) {
464 return false;
466 m_d->executeCmd(bp->enabled ? DCdisable : DCenable, bp->id);
467 } else {
468 bp->enabled = !bp->enabled;
469 emit breakpointsChanged();
471 return true;
474 bool KDebugger::conditionalBreakpoint(BrkptIterator bp,
475 const QString& condition,
476 int ignoreCount)
478 if (bp == m_brkpts.end())
479 return false;
482 * Change the condition and ignore count.
484 * The driver is not bothered if we are removing an orphaned
485 * breakpoint.
488 if (!bp->isOrphaned()) {
489 if (!canChangeBreakpoints()) {
490 return false;
493 bool changed = false;
495 if (bp->condition != condition) {
496 // change condition
497 m_d->executeCmd(DCcondition, condition, bp->id);
498 changed = true;
500 if (bp->ignoreCount != ignoreCount) {
501 // change ignore count
502 m_d->executeCmd(DCignore, bp->id, ignoreCount);
503 changed = true;
505 if (changed) {
506 // get the changes
507 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
509 } else {
510 bp->condition = condition;
511 bp->ignoreCount = ignoreCount;
512 emit breakpointsChanged();
514 return true;
517 bool KDebugger::deleteBreakpoint(BrkptIterator bp)
519 if (bp == m_brkpts.end())
520 return false;
523 * Remove the breakpoint.
525 * The driver is not bothered if we are removing an orphaned
526 * breakpoint.
528 if (!bp->isOrphaned()) {
529 if (!canChangeBreakpoints()) {
530 return false;
532 m_d->executeCmd(DCdelete, bp->id);
533 } else {
534 m_brkpts.erase(bp);
535 emit breakpointsChanged();
537 return false;
540 bool KDebugger::canSingleStep()
542 return isReady() && m_programActive && !m_programRunning;
545 bool KDebugger::canChangeBreakpoints()
547 return isReady() && !m_programRunning;
550 bool KDebugger::canStart()
552 return isReady() && !m_programActive;
555 bool KDebugger::isReady() const
557 return m_haveExecutable &&
558 m_d != 0 && m_d->canExecuteImmediately();
561 bool KDebugger::isIdle() const
563 return m_d == 0 || m_d->isIdle();
567 //////////////////////////////////////////////////////////
568 // debugger driver
570 bool KDebugger::startDriver()
572 emit debuggerStarting(); /* must set m_inferiorTerminal */
575 * If the per-program command string is empty, use the global setting
576 * (which might also be empty, in which case the driver uses its
577 * default).
579 m_explicitKill = false;
580 if (!m_d->startup(m_debuggerCmd)) {
581 return false;
585 * If we have an output terminal, we use it. Otherwise we will run the
586 * program with input and output redirected to /dev/null. Other
587 * redirections are also necessary depending on the tty emulation
588 * level.
590 int redirect = RDNstdin|RDNstdout|RDNstderr; /* redirect everything */
591 if (!m_inferiorTerminal.isEmpty()) {
592 switch (m_ttyLevel) {
593 default:
594 case ttyNone:
595 // redirect everything
596 break;
597 case ttySimpleOutputOnly:
598 redirect = RDNstdin;
599 break;
600 case ttyFull:
601 redirect = 0;
602 break;
605 m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
607 return true;
610 void KDebugger::stopDriver()
612 m_explicitKill = true;
614 if (m_attachedPid.isEmpty()) {
615 m_d->terminate();
616 } else {
617 m_d->detachAndTerminate();
621 * We MUST wait until the slot gdbExited() has been called. But to
622 * avoid a deadlock, we wait only for some certain maximum time. Should
623 * this timeout be reached, the only reasonable thing one could do then
624 * is exiting kdbg.
626 kapp->processEvents(1000); /* ideally, this will already shut it down */
627 int maxTime = 20; /* about 20 seconds */
628 while (m_haveExecutable && maxTime > 0) {
629 // give gdb time to die (and send a SIGCLD)
630 ::sleep(1);
631 --maxTime;
632 kapp->processEvents(1000);
636 void KDebugger::gdbExited(KProcess*)
639 * Save settings, but only if gdb has already processed "info line
640 * main", otherwise we would save an empty config file, because it
641 * isn't read in until then!
643 if (m_programConfig != 0) {
644 if (m_haveExecutable) {
645 saveProgramSettings();
646 m_programConfig->sync();
648 delete m_programConfig;
649 m_programConfig = 0;
652 // erase types
653 delete m_typeTable;
654 m_typeTable = 0;
656 if (m_explicitKill) {
657 TRACE(m_d->driverName() + " exited normally");
658 } else {
659 QString msg = i18n("%1 exited unexpectedly.\n"
660 "Restart the session (e.g. with File|Executable).");
661 KMessageBox::error(parentWidget(), msg.arg(m_d->driverName()));
664 // reset state
665 m_haveExecutable = false;
666 m_executable = "";
667 m_programActive = false;
668 m_programRunning = false;
669 m_explicitKill = false;
670 m_debuggerCmd = QString(); /* use global setting at next start! */
671 m_attachedPid = QString(); /* we are no longer attached to a process */
672 m_ttyLevel = ttyFull;
673 m_brkpts.clear();
675 // erase PC
676 emit updatePC(QString(), -1, DbgAddr(), 0);
679 QString KDebugger::getConfigForExe(const QString& name)
681 QFileInfo fi(name);
682 QString pgmConfigFile = fi.dirPath(true);
683 if (!pgmConfigFile.isEmpty()) {
684 pgmConfigFile += '/';
686 pgmConfigFile += ".kdbgrc." + fi.fileName();
687 TRACE("program config file = " + pgmConfigFile);
688 return pgmConfigFile;
691 void KDebugger::openProgramConfig(const QString& name)
693 ASSERT(m_programConfig == 0);
695 QString pgmConfigFile = getConfigForExe(name);
697 m_programConfig = new KConfig(pgmConfigFile);
700 const char EnvironmentGroup[] = "Environment";
701 const char WatchGroup[] = "Watches";
702 const char FileVersion[] = "FileVersion";
703 const char ProgramArgs[] = "ProgramArgs";
704 const char WorkingDirectory[] = "WorkingDirectory";
705 const char OptionsSelected[] = "OptionsSelected";
706 const char Variable[] = "Var%d";
707 const char Value[] = "Value%d";
708 const char ExprFmt[] = "Expr%d";
710 void KDebugger::saveProgramSettings()
712 ASSERT(m_programConfig != 0);
713 m_programConfig->setGroup(GeneralGroup);
714 m_programConfig->writeEntry(FileVersion, 1);
715 m_programConfig->writeEntry(ProgramArgs, m_programArgs);
716 m_programConfig->writeEntry(WorkingDirectory, m_programWD);
717 m_programConfig->writeEntry(OptionsSelected, m_boolOptions);
718 m_programConfig->writeEntry(DebuggerCmdStr, m_debuggerCmd);
719 m_programConfig->writeEntry(TTYLevelEntry, int(m_ttyLevel));
720 QString driverName;
721 if (m_d != 0)
722 driverName = m_d->driverName();
723 m_programConfig->writeEntry(DriverNameEntry, driverName);
725 // write environment variables
726 m_programConfig->deleteGroup(EnvironmentGroup);
727 m_programConfig->setGroup(EnvironmentGroup);
728 Q3DictIterator<EnvVar> it = m_envVars;
729 EnvVar* var;
730 QString varName;
731 QString varValue;
732 for (int i = 0; (var = it) != 0; ++it, ++i) {
733 varName.sprintf(Variable, i);
734 varValue.sprintf(Value, i);
735 m_programConfig->writeEntry(varName, it.currentKey());
736 m_programConfig->writeEntry(varValue, var->value);
739 saveBreakpoints(m_programConfig);
741 // watch expressions
742 // first get rid of whatever was in this group
743 m_programConfig->deleteGroup(WatchGroup);
744 // then start a new group
745 m_programConfig->setGroup(WatchGroup);
746 VarTree* item = m_watchVariables.firstChild();
747 int watchNum = 0;
748 for (; item != 0; item = item->nextSibling(), ++watchNum) {
749 varName.sprintf(ExprFmt, watchNum);
750 m_programConfig->writeEntry(varName, item->getText());
753 // give others a chance
754 emit saveProgramSpecific(m_programConfig);
757 void KDebugger::overrideProgramArguments(const QString& args)
759 ASSERT(m_programConfig != 0);
760 m_programConfig->setGroup(GeneralGroup);
761 m_programConfig->writeEntry(ProgramArgs, args);
764 void KDebugger::restoreProgramSettings()
766 ASSERT(m_programConfig != 0);
767 m_programConfig->setGroup(GeneralGroup);
769 * We ignore file version for now we will use it in the future to
770 * distinguish different versions of this configuration file.
772 // m_debuggerCmd has been read in already
773 // m_ttyLevel has been read in already
774 QString pgmArgs = m_programConfig->readEntry(ProgramArgs);
775 QString pgmWd = m_programConfig->readEntry(WorkingDirectory);
776 QStringList boolOptions = m_programConfig->readListEntry(OptionsSelected);
777 m_boolOptions = QStringList();
779 // read environment variables
780 m_programConfig->setGroup(EnvironmentGroup);
781 m_envVars.clear();
782 Q3Dict<EnvVar> pgmVars;
783 EnvVar* var;
784 QString varName;
785 QString varValue;
786 for (int i = 0;; ++i) {
787 varName.sprintf(Variable, i);
788 varValue.sprintf(Value, i);
789 if (!m_programConfig->hasKey(varName)) {
790 /* entry not present, assume that we've hit them all */
791 break;
793 QString name = m_programConfig->readEntry(varName);
794 if (name.isEmpty()) {
795 // skip empty names
796 continue;
798 var = new EnvVar;
799 var->value = m_programConfig->readEntry(varValue);
800 var->status = EnvVar::EVnew;
801 pgmVars.insert(name, var);
804 updateProgEnvironment(pgmArgs, pgmWd, pgmVars, boolOptions);
806 restoreBreakpoints(m_programConfig);
808 // watch expressions
809 m_programConfig->setGroup(WatchGroup);
810 m_watchVariables.clear();
811 for (int i = 0;; ++i) {
812 varName.sprintf(ExprFmt, i);
813 if (!m_programConfig->hasKey(varName)) {
814 /* entry not present, assume that we've hit them all */
815 break;
817 QString expr = m_programConfig->readEntry(varName);
818 if (expr.isEmpty()) {
819 // skip empty expressions
820 continue;
822 addWatch(expr);
825 // give others a chance
826 emit restoreProgramSpecific(m_programConfig);
830 * Reads the debugger command line from the program settings. The config
831 * group must have been set by the caller.
833 QString KDebugger::readDebuggerCmd()
835 QString debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
837 // always let the user confirm the debugger cmd if we are root
838 if (::geteuid() == 0)
840 if (!debuggerCmd.isEmpty()) {
841 QString msg = i18n(
842 "The settings for this program specify "
843 "the following debugger command:\n%1\n"
844 "Shall this command be used?");
845 if (KMessageBox::warningYesNo(parentWidget(), msg.arg(debuggerCmd))
846 != KMessageBox::Yes)
848 // don't use it
849 debuggerCmd = QString();
853 return debuggerCmd;
857 * Breakpoints are saved one per group.
859 const char BPGroup[] = "Breakpoint %d";
860 const char File[] = "File";
861 const char Line[] = "Line";
862 const char Text[] = "Text";
863 const char Address[] = "Address";
864 const char Temporary[] = "Temporary";
865 const char Enabled[] = "Enabled";
866 const char Condition[] = "Condition";
868 void KDebugger::saveBreakpoints(KConfig* config)
870 QString groupName;
871 int i = 0;
872 for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
874 if (bp->type == Breakpoint::watchpoint)
875 continue; /* don't save watchpoints */
876 groupName.sprintf(BPGroup, i++);
878 /* remove remmants */
879 config->deleteGroup(groupName);
881 config->setGroup(groupName);
882 if (!bp->text.isEmpty()) {
884 * The breakpoint was set using the text box in the breakpoint
885 * list. We do not save the location by filename+line number,
886 * but instead honor what the user typed (a function name, for
887 * example, which could move between sessions).
889 config->writeEntry(Text, bp->text);
890 } else if (!bp->fileName.isEmpty()) {
891 config->writeEntry(File, bp->fileName);
892 config->writeEntry(Line, bp->lineNo);
894 * Addresses are hardly correct across sessions, so we don't
895 * save it.
897 } else {
898 config->writeEntry(Address, bp->address.asString());
900 config->writeEntry(Temporary, bp->temporary);
901 config->writeEntry(Enabled, bp->enabled);
902 if (!bp->condition.isEmpty())
903 config->writeEntry(Condition, bp->condition);
904 // we do not save the ignore count
906 // delete remaining groups
907 // we recognize that a group is present if there is an Enabled entry
908 for (;; i++) {
909 groupName.sprintf(BPGroup, i);
910 config->setGroup(groupName);
911 if (!config->hasKey(Enabled)) {
912 /* group not present, assume that we've hit them all */
913 break;
915 config->deleteGroup(groupName);
919 void KDebugger::restoreBreakpoints(KConfig* config)
921 QString groupName;
923 * We recognize the end of the list if there is no Enabled entry
924 * present.
926 for (int i = 0;; i++) {
927 groupName.sprintf(BPGroup, i);
928 config->setGroup(groupName);
929 if (!config->hasKey(Enabled)) {
930 /* group not present, assume that we've hit them all */
931 break;
933 Breakpoint* bp = new Breakpoint;
934 bp->fileName = config->readEntry(File);
935 bp->lineNo = config->readNumEntry(Line, -1);
936 bp->text = config->readEntry(Text);
937 bp->address = config->readEntry(Address);
938 // check consistency
939 if ((bp->fileName.isEmpty() || bp->lineNo < 0) &&
940 bp->text.isEmpty() &&
941 bp->address.isEmpty())
943 delete bp;
944 continue;
946 bp->enabled = config->readBoolEntry(Enabled, true);
947 bp->temporary = config->readBoolEntry(Temporary, false);
948 bp->condition = config->readEntry(Condition);
951 * Add the breakpoint.
953 setBreakpoint(bp, false);
954 // the new breakpoint is disabled or conditionalized later
955 // in newBreakpoint()
957 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
961 // parse output of command cmd
962 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
964 ASSERT(cmd != 0); /* queue mustn't be empty */
966 TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
968 switch (cmd->m_cmd) {
969 case DCtargetremote:
970 // the output (if any) is uninteresting
971 case DCsetargs:
972 case DCtty:
973 // there is no output
974 case DCsetenv:
975 case DCunsetenv:
976 case DCsetoption:
977 /* if value is empty, we see output, but we don't care */
978 break;
979 case DCcd:
980 /* display gdb's message in the status bar */
981 m_d->parseChangeWD(output, m_statusMessage);
982 emit updateStatusMessage();
983 break;
984 case DCinitialize:
985 break;
986 case DCexecutable:
987 if (m_d->parseChangeExecutable(output, m_statusMessage))
989 // success; restore breakpoints etc.
990 if (m_programConfig != 0) {
991 restoreProgramSettings();
993 // load file containing main() or core file
994 if (!m_corefile.isEmpty())
996 // load core file
997 loadCoreFile();
999 else if (!m_attachedPid.isEmpty())
1001 m_d->queueCmd(DCattach, m_attachedPid, DebuggerDriver::QMoverride);
1002 m_programActive = true;
1003 m_programRunning = true;
1005 else if (!m_remoteDevice.isEmpty())
1007 // handled elsewhere
1009 else
1011 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
1013 if (!m_statusMessage.isEmpty())
1014 emit updateStatusMessage();
1015 } else {
1016 QString msg = m_d->driverName() + ": " + m_statusMessage;
1017 KMessageBox::sorry(parentWidget(), msg);
1018 m_executable = "";
1019 m_corefile = ""; /* don't process core file */
1020 m_haveExecutable = false;
1022 break;
1023 case DCcorefile:
1024 // in any event we have an executable at this point
1025 m_haveExecutable = true;
1026 if (m_d->parseCoreFile(output)) {
1027 // loading a core is like stopping at a breakpoint
1028 m_programActive = true;
1029 handleRunCommands(output);
1030 // do not reset m_corefile
1031 } else {
1032 // report error
1033 QString msg = m_d->driverName() + ": " + QString(output);
1034 KMessageBox::sorry(parentWidget(), msg);
1036 // if core file was loaded from command line, revert to info line main
1037 if (!cmd->m_byUser) {
1038 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
1040 m_corefile = QString(); /* core file not available any more */
1042 break;
1043 case DCinfolinemain:
1044 // ignore the output, marked file info follows
1045 m_haveExecutable = true;
1046 break;
1047 case DCinfolocals:
1048 // parse local variables
1049 if (output[0] != '\0') {
1050 handleLocals(output);
1052 break;
1053 case DCinforegisters:
1054 handleRegisters(output);
1055 break;
1056 case DCexamine:
1057 handleMemoryDump(output);
1058 break;
1059 case DCinfoline:
1060 handleInfoLine(cmd, output);
1061 break;
1062 case DCdisassemble:
1063 handleDisassemble(cmd, output);
1064 break;
1065 case DCframe:
1066 handleFrameChange(output);
1067 updateAllExprs();
1068 break;
1069 case DCbt:
1070 handleBacktrace(output);
1071 updateAllExprs();
1072 break;
1073 case DCprint:
1074 handlePrint(cmd, output);
1075 break;
1076 case DCprintDeref:
1077 handlePrintDeref(cmd, output);
1078 break;
1079 case DCattach:
1080 m_haveExecutable = true;
1081 // fall through
1082 case DCrun:
1083 case DCcont:
1084 case DCstep:
1085 case DCstepi:
1086 case DCnext:
1087 case DCnexti:
1088 case DCfinish:
1089 case DCuntil:
1090 case DCthread:
1091 handleRunCommands(output);
1092 break;
1093 case DCkill:
1094 m_programRunning = m_programActive = false;
1095 // erase PC
1096 emit updatePC(QString(), -1, DbgAddr(), 0);
1097 break;
1098 case DCbreaktext:
1099 case DCbreakline:
1100 case DCtbreakline:
1101 case DCbreakaddr:
1102 case DCtbreakaddr:
1103 case DCwatchpoint:
1104 newBreakpoint(cmd, output);
1105 // fall through
1106 case DCdelete:
1107 case DCenable:
1108 case DCdisable:
1109 // these commands need immediate response
1110 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverrideMoreEqual);
1111 break;
1112 case DCinfobreak:
1113 // note: this handler must not enqueue a command, since
1114 // DCinfobreak is used at various different places.
1115 updateBreakList(output);
1116 break;
1117 case DCfindType:
1118 handleFindType(cmd, output);
1119 break;
1120 case DCprintStruct:
1121 case DCprintQStringStruct:
1122 case DCprintWChar:
1123 handlePrintStruct(cmd, output);
1124 break;
1125 case DCinfosharedlib:
1126 handleSharedLibs(output);
1127 break;
1128 case DCcondition:
1129 case DCignore:
1130 // we are not interested in the output
1131 break;
1132 case DCinfothreads:
1133 handleThreadList(output);
1134 break;
1135 case DCsetpc:
1136 handleSetPC(output);
1137 break;
1138 case DCsetvariable:
1139 handleSetVariable(cmd, output);
1140 break;
1144 void KDebugger::backgroundUpdate()
1147 * If there are still expressions that need to be updated, then do so.
1149 if (m_programActive)
1150 evalExpressions();
1153 void KDebugger::handleRunCommands(const char* output)
1155 uint flags = m_d->parseProgramStopped(output, m_statusMessage);
1156 emit updateStatusMessage();
1158 m_programActive = flags & DebuggerDriver::SFprogramActive;
1160 // refresh files if necessary
1161 if (flags & DebuggerDriver::SFrefreshSource) {
1162 TRACE("re-reading files");
1163 emit executableUpdated();
1167 * Try to set any orphaned breakpoints now.
1169 for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
1171 if (bp->isOrphaned()) {
1172 TRACE(QString("re-trying brkpt loc: %2 file: %3 line: %1")
1173 .arg(bp->lineNo).arg(bp->location, bp->fileName));
1174 CmdQueueItem* cmd = executeBreakpoint(&*bp, true);
1175 cmd->m_existingBrkpt = bp->id; // used in newBreakpoint()
1176 flags |= DebuggerDriver::SFrefreshBreak;
1181 * If we stopped at a breakpoint, we must update the breakpoint list
1182 * because the hit count changes. Also, if the breakpoint was temporary
1183 * it would go away now.
1185 if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
1186 stopMayChangeBreakList())
1188 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
1192 * If we haven't listed the shared libraries yet, do so. We must do
1193 * this before we emit any commands that list variables, since the type
1194 * libraries depend on the shared libraries.
1196 if (!m_sharedLibsListed) {
1197 // must be a high-priority command!
1198 m_d->executeCmd(DCinfosharedlib);
1201 // get the backtrace if the program is running
1202 if (m_programActive) {
1203 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
1204 } else {
1205 // program finished: erase PC
1206 emit updatePC(QString(), -1, DbgAddr(), 0);
1207 // dequeue any commands in the queues
1208 m_d->flushCommands();
1211 /* Update threads list */
1212 if (m_programActive && (flags & DebuggerDriver::SFrefreshThreads)) {
1213 m_d->queueCmd(DCinfothreads, DebuggerDriver::QMoverride);
1216 m_programRunning = false;
1217 emit programStopped();
1220 void KDebugger::slotInferiorRunning()
1222 m_programRunning = true;
1225 void KDebugger::updateAllExprs()
1227 if (!m_programActive)
1228 return;
1230 // retrieve local variables
1231 m_d->queueCmd(DCinfolocals, DebuggerDriver::QMoverride);
1233 // retrieve registers
1234 m_d->queueCmd(DCinforegisters, DebuggerDriver::QMoverride);
1236 // get new memory dump
1237 if (!m_memoryExpression.isEmpty()) {
1238 queueMemoryDump(false);
1241 // update watch expressions
1242 VarTree* item = m_watchVariables.firstChild();
1243 for (; item != 0; item = item->nextSibling()) {
1244 m_watchEvalExpr.push_back(item->getText());
1248 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
1249 const Q3Dict<EnvVar>& newVars,
1250 const QStringList& newOptions)
1252 m_programArgs = args;
1253 m_d->executeCmd(DCsetargs, m_programArgs);
1254 TRACE("new pgm args: " + m_programArgs + "\n");
1256 m_programWD = wd.stripWhiteSpace();
1257 if (!m_programWD.isEmpty()) {
1258 m_d->executeCmd(DCcd, m_programWD);
1259 TRACE("new wd: " + m_programWD + "\n");
1262 // update environment variables
1263 Q3DictIterator<EnvVar> it = newVars;
1264 EnvVar* val;
1265 for (; (val = it) != 0; ++it) {
1266 QString var = it.currentKey();
1267 switch (val->status) {
1268 case EnvVar::EVnew:
1269 m_envVars.insert(var, val);
1270 // fall thru
1271 case EnvVar::EVdirty:
1272 // the value must be in our list
1273 ASSERT(m_envVars[var] == val);
1274 // update value
1275 m_d->executeCmd(DCsetenv, var, val->value);
1276 break;
1277 case EnvVar::EVdeleted:
1278 // must be in our list
1279 ASSERT(m_envVars[var] == val);
1280 // delete value
1281 m_d->executeCmd(DCunsetenv, var);
1282 m_envVars.remove(var);
1283 break;
1284 default:
1285 ASSERT(false);
1286 case EnvVar::EVclean:
1287 // variable not changed
1288 break;
1292 // update options
1293 QStringList::ConstIterator oi;
1294 for (oi = newOptions.begin(); oi != newOptions.end(); ++oi)
1296 if (m_boolOptions.findIndex(*oi) < 0) {
1297 // the options is currently not set, so set it
1298 m_d->executeCmd(DCsetoption, *oi, 1);
1299 } else {
1300 // option is set, no action required, but move it to the end
1301 m_boolOptions.remove(*oi);
1303 m_boolOptions.append(*oi);
1306 * Now all options that should be set are at the end of m_boolOptions.
1307 * If some options need to be unset, they are at the front of the list.
1308 * Here we unset and remove them.
1310 while (m_boolOptions.count() > newOptions.count()) {
1311 m_d->executeCmd(DCsetoption, m_boolOptions.first(), 0);
1312 m_boolOptions.remove(m_boolOptions.begin());
1316 void KDebugger::handleLocals(const char* output)
1318 // retrieve old list of local variables
1319 QStringList oldVars = m_localVariables.exprList();
1322 * Get local variables.
1324 std::list<ExprValue*> newVars;
1325 parseLocals(output, newVars);
1328 * Clear any old VarTree item pointers, so that later we don't access
1329 * dangling pointers.
1331 m_localVariables.clearPendingUpdates();
1334 * Match old variables against new ones.
1336 for (QStringList::ConstIterator n = oldVars.begin(); n != oldVars.end(); ++n) {
1337 // lookup this variable in the list of new variables
1338 std::list<ExprValue*>::iterator v = newVars.begin();
1339 while (v != newVars.end() && (*v)->m_name != *n)
1340 ++v;
1341 if (v == newVars.end()) {
1342 // old variable not in the new variables
1343 TRACE("old var deleted: " + *n);
1344 VarTree* v = m_localVariables.topLevelExprByName(*n);
1345 if (v != 0) {
1346 m_localVariables.removeExpr(v);
1348 } else {
1349 // variable in both old and new lists: update
1350 TRACE("update var: " + *n);
1351 m_localVariables.updateExpr(*v, *m_typeTable);
1352 // remove the new variable from the list
1353 delete *v;
1354 newVars.erase(v);
1357 // insert all remaining new variables
1358 while (!newVars.empty())
1360 ExprValue* v = newVars.front();
1361 TRACE("new var: " + v->m_name);
1362 m_localVariables.insertExpr(v, *m_typeTable);
1363 delete v;
1364 newVars.pop_front();
1368 void KDebugger::parseLocals(const char* output, std::list<ExprValue*>& newVars)
1370 std::list<ExprValue*> vars;
1371 m_d->parseLocals(output, vars);
1373 QString origName; /* used in renaming variables */
1374 while (!vars.empty())
1376 ExprValue* variable = vars.front();
1377 vars.pop_front();
1379 * When gdb prints local variables, those from the innermost block
1380 * come first. We run through the list of already parsed variables
1381 * to find duplicates (ie. variables that hide local variables from
1382 * a surrounding block). We keep the name of the inner variable, but
1383 * rename those from the outer block so that, when the value is
1384 * updated in the window, the value of the variable that is
1385 * _visible_ changes the color!
1387 int block = 0;
1388 origName = variable->m_name;
1389 for (std::list<ExprValue*>::iterator v = newVars.begin(); v != newVars.end(); ++v) {
1390 if (variable->m_name == (*v)->m_name) {
1391 // we found a duplicate, change name
1392 block++;
1393 QString newName = origName + " (" + QString().setNum(block) + ")";
1394 variable->m_name = newName;
1397 newVars.push_back(variable);
1401 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1403 ASSERT(cmd->m_expr != 0);
1405 ExprValue* variable = m_d->parsePrintExpr(output, true);
1406 if (variable == 0)
1407 return false;
1409 // set expression "name"
1410 variable->m_name = cmd->m_expr->getText();
1413 TRACE("update expr: " + cmd->m_expr->getText());
1414 cmd->m_exprWnd->updateExpr(cmd->m_expr, variable, *m_typeTable);
1415 delete variable;
1418 evalExpressions(); /* enqueue dereferenced pointers */
1420 return true;
1423 bool KDebugger::handlePrintDeref(CmdQueueItem* cmd, const char* output)
1425 ASSERT(cmd->m_expr != 0);
1427 ExprValue* variable = m_d->parsePrintExpr(output, true);
1428 if (variable == 0)
1429 return false;
1431 // set expression "name"
1432 variable->m_name = cmd->m_expr->getText();
1436 * We must insert a dummy parent, because otherwise variable's value
1437 * would overwrite cmd->m_expr's value.
1439 ExprValue* dummyParent = new ExprValue(variable->m_name, VarTree::NKplain);
1440 dummyParent->m_varKind = VarTree::VKdummy;
1441 // the name of the parsed variable is the address of the pointer
1442 QString addr = "*" + cmd->m_expr->value();
1443 variable->m_name = addr;
1444 variable->m_nameKind = VarTree::NKaddress;
1446 dummyParent->m_child = variable;
1447 // expand the first level for convenience
1448 variable->m_initiallyExpanded = true;
1449 TRACE("update ptr: " + cmd->m_expr->getText());
1450 cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent, *m_typeTable);
1451 delete dummyParent;
1454 evalExpressions(); /* enqueue dereferenced pointers */
1456 return true;
1459 // parse the output of bt
1460 void KDebugger::handleBacktrace(const char* output)
1462 // reduce flicker
1463 m_btWindow.setAutoUpdate(false);
1465 m_btWindow.clear();
1467 std::list<StackFrame> stack;
1468 m_d->parseBackTrace(output, stack);
1470 if (!stack.empty()) {
1471 std::list<StackFrame>::iterator frm = stack.begin();
1472 // first frame must set PC
1473 // note: frm->lineNo is zero-based
1474 emit updatePC(frm->fileName, frm->lineNo, frm->address, frm->frameNo);
1476 for (; frm != stack.end(); ++frm) {
1477 QString func;
1478 if (frm->var != 0)
1479 func = frm->var->m_name;
1480 else
1481 func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1482 m_btWindow.insertItem(func);
1483 TRACE("frame " + func + " (" + frm->fileName + ":" +
1484 QString().setNum(frm->lineNo+1) + ")");
1488 m_btWindow.setAutoUpdate(true);
1489 m_btWindow.repaint();
1492 void KDebugger::gotoFrame(int frame)
1494 m_d->executeCmd(DCframe, frame);
1497 void KDebugger::handleFrameChange(const char* output)
1499 QString fileName;
1500 int frameNo;
1501 int lineNo;
1502 DbgAddr address;
1503 if (m_d->parseFrameChange(output, frameNo, fileName, lineNo, address)) {
1504 /* lineNo can be negative here if we can't find a file name */
1505 emit updatePC(fileName, lineNo, address, frameNo);
1506 } else {
1507 emit updatePC(fileName, -1, address, frameNo);
1511 void KDebugger::evalExpressions()
1513 // evaluate expressions in the following order:
1514 // watch expressions
1515 // pointers in local variables
1516 // pointers in watch expressions
1517 // types in local variables
1518 // types in watch expressions
1519 // struct members in local variables
1520 // struct members in watch expressions
1521 VarTree* exprItem = 0;
1522 if (!m_watchEvalExpr.empty())
1524 QString expr = m_watchEvalExpr.front();
1525 m_watchEvalExpr.pop_front();
1526 exprItem = m_watchVariables.topLevelExprByName(expr);
1528 if (exprItem != 0) {
1529 CmdQueueItem* cmd = m_d->queueCmd(DCprint, exprItem->getText(), DebuggerDriver::QMoverride);
1530 // remember which expr this was
1531 cmd->m_expr = exprItem;
1532 cmd->m_exprWnd = &m_watchVariables;
1533 } else {
1534 ExprWnd* wnd;
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 ExprValue* 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 = m_d->parsePrintExpr(output, false);
1668 bool errorValue =
1669 partExpr == 0 ||
1670 /* we only allow simple values at the moment */
1671 partExpr->m_child != 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 expr;
1755 if (var->m_exprIndexUseGuard) {
1756 expr = var->m_type->m_guardStrings[var->m_exprIndex];
1757 if (expr.isEmpty()) {
1758 // no guard, omit it and go to expression
1759 var->m_exprIndexUseGuard = false;
1762 if (!var->m_exprIndexUseGuard) {
1763 expr = var->m_type->m_exprStrings[var->m_exprIndex];
1766 expr.replace("%s", base);
1768 DbgCommand dbgCmd = DCprintStruct;
1769 // check if this is a QString::Data
1770 if (expr.left(15) == "/QString::Data ")
1772 if (m_typeTable->parseQt2QStrings())
1774 expr = expr.mid(15, expr.length()); /* strip off /QString::Data */
1775 dbgCmd = DCprintQStringStruct;
1776 } else {
1778 * This should not happen: the type libraries should be set up
1779 * in a way that this can't happen. If this happens
1780 * nevertheless it means that, eg., kdecore was loaded but qt2
1781 * was not (only qt2 enables the QString feature).
1783 // TODO: remove this "print"; queue the next printStruct instead
1784 expr = "*0";
1787 TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1788 CmdQueueItem* cmd = m_d->queueCmd(dbgCmd, expr,
1789 immediate ? DebuggerDriver::QMoverrideMoreEqual
1790 : DebuggerDriver::QMnormal);
1792 // remember which expression this was
1793 cmd->m_expr = var;
1794 cmd->m_exprWnd = wnd;
1797 void KDebugger::handleSharedLibs(const char* output)
1799 // parse the table of shared libraries
1800 m_sharedLibs = m_d->parseSharedLibs(output);
1801 m_sharedLibsListed = true;
1803 // get type libraries
1804 m_typeTable->loadLibTypes(m_sharedLibs);
1806 // hand over the QString data cmd
1807 m_d->setPrintQStringDataCmd(m_typeTable->printQStringDataCmd());
1810 CmdQueueItem* KDebugger::loadCoreFile()
1812 return m_d->queueCmd(DCcorefile, m_corefile, DebuggerDriver::QMoverride);
1815 void KDebugger::slotExpanding(Q3ListViewItem* item)
1817 VarTree* exprItem = static_cast<VarTree*>(item);
1818 if (exprItem->m_varKind != VarTree::VKpointer) {
1819 return;
1821 ExprWnd* wnd = static_cast<ExprWnd*>(item->listView());
1822 dereferencePointer(wnd, exprItem, true);
1825 // add the expression in the edit field to the watch expressions
1826 void KDebugger::addWatch(const QString& t)
1828 QString expr = t.stripWhiteSpace();
1829 // don't add a watched expression again
1830 if (expr.isEmpty() || m_watchVariables.topLevelExprByName(expr) != 0)
1831 return;
1832 ExprValue e(expr, VarTree::NKplain);
1833 m_watchVariables.insertExpr(&e, *m_typeTable);
1835 // if we are boring ourselves, send down the command
1836 if (m_programActive) {
1837 m_watchEvalExpr.push_back(expr);
1838 if (m_d->isIdle()) {
1839 evalExpressions();
1844 // delete a toplevel watch expression
1845 void KDebugger::slotDeleteWatch()
1847 // delete only allowed while debugger is idle; or else we might delete
1848 // the very expression the debugger is currently working on...
1849 if (m_d == 0 || !m_d->isIdle())
1850 return;
1852 VarTree* item = m_watchVariables.currentItem();
1853 if (item == 0 || !item->isToplevelExpr())
1854 return;
1856 // remove the variable from the list to evaluate
1857 QStringList::iterator i = m_watchEvalExpr.find(item->getText());
1858 if (i != m_watchEvalExpr.end()) {
1859 m_watchEvalExpr.erase(i);
1861 m_watchVariables.removeExpr(item);
1862 // item is invalid at this point!
1865 void KDebugger::handleRegisters(const char* output)
1867 emit registersChanged(m_d->parseRegisters(output));
1871 * The output of the DCbreak* commands has more accurate information about
1872 * the file and the line number.
1874 * All newly set breakpoints are inserted in the m_brkpts, even those that
1875 * were not set sucessfully. The unsuccessful breakpoints ("orphaned
1876 * breakpoints") are assigned negative ids, and they are tried to set later
1877 * when the program stops again at a breakpoint.
1879 void KDebugger::newBreakpoint(CmdQueueItem* cmd, const char* output)
1881 BrkptIterator bp;
1882 if (cmd->m_brkpt != 0) {
1883 // a new breakpoint, put it in the list
1884 assert(cmd->m_brkpt->id == 0);
1885 m_brkpts.push_back(*cmd->m_brkpt);
1886 delete cmd->m_brkpt;
1887 bp = m_brkpts.end();
1888 --bp;
1889 } else {
1890 // an existing breakpoint was retried
1891 assert(cmd->m_existingBrkpt != 0);
1892 bp = breakpointById(cmd->m_existingBrkpt);
1893 if (bp == m_brkpts.end())
1894 return;
1897 // parse the output to determine success or failure
1898 int id;
1899 QString file;
1900 int lineNo;
1901 QString address;
1902 if (!m_d->parseBreakpoint(output, id, file, lineNo, address))
1905 * Failure, the breakpoint could not be set. If this is a new
1906 * breakpoint, assign it a negative id. We look for the minimal id
1907 * of all breakpoints (that are already in the list) to get the new
1908 * id.
1910 if (bp->id == 0)
1912 int minId = 0;
1913 for (BrkptIterator i = m_brkpts.begin(); i != m_brkpts.end(); ++i) {
1914 if (i->id < minId)
1915 minId = i->id;
1917 bp->id = minId-1;
1919 return;
1922 // The breakpoint was successfully set.
1923 if (bp->id <= 0)
1925 // this is a new or orphaned breakpoint:
1926 // set the remaining properties
1927 if (!bp->enabled) {
1928 m_d->executeCmd(DCdisable, id);
1930 if (!bp->condition.isEmpty()) {
1931 m_d->executeCmd(DCcondition, bp->condition, id);
1935 bp->id = id;
1936 bp->fileName = file;
1937 bp->lineNo = lineNo;
1938 if (!address.isEmpty())
1939 bp->address = address;
1942 void KDebugger::updateBreakList(const char* output)
1944 // get the new list
1945 std::list<Breakpoint> brks;
1946 m_d->parseBreakList(output, brks);
1948 // merge existing information into the new list
1949 // then swap the old and new lists
1951 for (BrkptIterator bp = brks.begin(); bp != brks.end(); ++bp)
1953 BrkptIterator i = breakpointById(bp->id);
1954 if (i != m_brkpts.end())
1956 // preserve accurate location information
1957 // note that xsldbg doesn't have a location in
1958 // the listed breakpoint if it has just been set
1959 // therefore, we copy it as well if necessary
1960 bp->text = i->text;
1961 if (!i->fileName.isEmpty()) {
1962 bp->fileName = i->fileName;
1963 bp->lineNo = i->lineNo;
1968 // orphaned breakpoints must be copied
1969 for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
1971 if (bp->isOrphaned())
1972 brks.push_back(*bp);
1975 m_brkpts.swap(brks);
1976 emit breakpointsChanged();
1979 // look if there is at least one temporary breakpoint
1980 // or a watchpoint
1981 bool KDebugger::stopMayChangeBreakList() const
1983 for (BrkptROIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
1985 if (bp->temporary || bp->type == Breakpoint::watchpoint)
1986 return true;
1988 return false;
1991 KDebugger::BrkptIterator KDebugger::breakpointByFilePos(QString file, int lineNo,
1992 const DbgAddr& address)
1994 // look for exact file name match
1995 for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
1997 if (bp->lineNo == lineNo &&
1998 bp->fileName == file &&
1999 (address.isEmpty() || bp->address == address))
2001 return bp;
2004 // not found, so try basename
2005 // strip off directory part of file name
2006 int offset = file.findRev("/");
2007 file.remove(0, offset+1);
2009 for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
2011 // get base name of breakpoint's file
2012 QString basename = bp->fileName;
2013 int offset = basename.findRev("/");
2014 if (offset >= 0) {
2015 basename.remove(0, offset+1);
2018 if (bp->lineNo == lineNo &&
2019 basename == file &&
2020 (address.isEmpty() || bp->address == address))
2022 return bp;
2026 // not found
2027 return m_brkpts.end();
2030 KDebugger::BrkptIterator KDebugger::breakpointById(int id)
2032 for (BrkptIterator bp = m_brkpts.begin(); bp != m_brkpts.end(); ++bp)
2034 if (bp->id == id) {
2035 return bp;
2038 // not found
2039 return m_brkpts.end();
2042 void KDebugger::slotValuePopup(const QString& expr)
2044 // search the local variables for a match
2045 VarTree* v = m_localVariables.topLevelExprByName(expr);
2046 if (v == 0) {
2047 // not found, check watch expressions
2048 v = m_watchVariables.topLevelExprByName(expr);
2049 if (v == 0) {
2050 // try a member of 'this'
2051 v = m_localVariables.topLevelExprByName("this");
2052 if (v != 0)
2053 v = ExprWnd::ptrMemberByName(v, expr);
2054 if (v == 0) {
2055 // nothing found; do nothing
2056 return;
2061 // construct the tip
2062 QString tip = v->getText() + " = ";
2063 if (!v->value().isEmpty())
2065 tip += v->value();
2067 else
2069 // no value: we use some hint
2070 switch (v->m_varKind) {
2071 case VarTree::VKstruct:
2072 tip += "{...}";
2073 break;
2074 case VarTree::VKarray:
2075 tip += "[...]";
2076 break;
2077 default:
2078 tip += "?""?""?"; // 2 question marks in a row would be a trigraph
2079 break;
2082 emit valuePopup(tip);
2085 void KDebugger::slotDisassemble(const QString& fileName, int lineNo)
2087 if (m_haveExecutable) {
2088 CmdQueueItem* cmd = m_d->queueCmd(DCinfoline, fileName, lineNo,
2089 DebuggerDriver::QMoverrideMoreEqual);
2090 cmd->m_fileName = fileName;
2091 cmd->m_lineNo = lineNo;
2095 void KDebugger::handleInfoLine(CmdQueueItem* cmd, const char* output)
2097 QString addrFrom, addrTo;
2098 if (cmd->m_lineNo >= 0) {
2099 // disassemble
2100 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2101 // got the address range, now get the real code
2102 CmdQueueItem* c = m_d->queueCmd(DCdisassemble, addrFrom, addrTo,
2103 DebuggerDriver::QMoverrideMoreEqual);
2104 c->m_fileName = cmd->m_fileName;
2105 c->m_lineNo = cmd->m_lineNo;
2106 } else {
2107 // no code
2108 emit disassembled(cmd->m_fileName, cmd->m_lineNo, std::list<DisassembledCode>());
2110 } else {
2111 // set program counter
2112 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2113 // move the program counter to the start address
2114 m_d->executeCmd(DCsetpc, addrFrom);
2119 void KDebugger::handleDisassemble(CmdQueueItem* cmd, const char* output)
2121 emit disassembled(cmd->m_fileName, cmd->m_lineNo,
2122 m_d->parseDisassemble(output));
2125 void KDebugger::handleThreadList(const char* output)
2127 emit threadsChanged(m_d->parseThreadList(output));
2130 void KDebugger::setThread(int id)
2132 m_d->queueCmd(DCthread, id, DebuggerDriver::QMoverrideMoreEqual);
2135 void KDebugger::setMemoryExpression(const QString& memexpr)
2137 m_memoryExpression = memexpr;
2139 // queue the new expression
2140 if (!m_memoryExpression.isEmpty() &&
2141 isProgramActive() &&
2142 !isProgramRunning())
2144 queueMemoryDump(true);
2148 void KDebugger::queueMemoryDump(bool immediate)
2150 m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat,
2151 immediate ? DebuggerDriver::QMoverrideMoreEqual :
2152 DebuggerDriver::QMoverride);
2155 void KDebugger::handleMemoryDump(const char* output)
2157 std::list<MemoryDump> memdump;
2158 QString msg = m_d->parseMemoryDump(output, memdump);
2159 emit memoryDumpChanged(msg, memdump);
2162 void KDebugger::setProgramCounter(const QString& file, int line, const DbgAddr& addr)
2164 if (addr.isEmpty()) {
2165 // find address of the specified line
2166 CmdQueueItem* cmd = m_d->executeCmd(DCinfoline, file, line);
2167 cmd->m_lineNo = -1; /* indicates "Set PC" UI command */
2168 } else {
2169 // move the program counter to that address
2170 m_d->executeCmd(DCsetpc, addr.asString());
2174 void KDebugger::handleSetPC(const char* /*output*/)
2176 // TODO: handle errors
2178 // now go to the top-most frame
2179 // this also modifies the program counter indicator in the UI
2180 gotoFrame(0);
2183 void KDebugger::slotValueEdited(VarTree* expr, const QString& text)
2185 if (text.simplifyWhiteSpace().isEmpty())
2186 return; /* no text entered: ignore request */
2188 ExprWnd* wnd = static_cast<ExprWnd*>(expr->listView());
2189 TRACE(QString().sprintf("Changing %s to ",
2190 wnd->name()) + text);
2192 // determine the lvalue to edit
2193 QString lvalue = expr->computeExpr();
2194 CmdQueueItem* cmd = m_d->executeCmd(DCsetvariable, lvalue, text);
2195 cmd->m_expr = expr;
2196 cmd->m_exprWnd = wnd;
2199 void KDebugger::handleSetVariable(CmdQueueItem* cmd, const char* output)
2201 QString msg = m_d->parseSetVariable(output);
2202 if (!msg.isEmpty())
2204 // there was an error; display it in the status bar
2205 m_statusMessage = msg;
2206 emit updateStatusMessage();
2207 return;
2210 // get the new value
2211 QString expr = cmd->m_expr->computeExpr();
2212 CmdQueueItem* printCmd =
2213 m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverrideMoreEqual);
2214 printCmd->m_expr = cmd->m_expr;
2215 printCmd->m_exprWnd = cmd->m_exprWnd;
2219 #include "debugger.moc"