Document how to specify templates in type tables.
[kdbg.git] / kdbg / debugger.cpp
blobdc9b61ec3be59a071e15ef0933a8e370d9ba2645
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 "programconfig.h"
14 #include "valarray.h"
15 #include <qregexp.h>
16 #include <qfileinfo.h>
17 #include <qlistbox.h>
18 #include <qstringlist.h>
19 #include <kapp.h>
20 #include <kconfig.h>
21 #include <klocale.h> /* i18n */
22 #include <kmessagebox.h>
23 #include <ctype.h>
24 #include <stdlib.h> /* strtol, atoi */
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h> /* sleep(3) */
27 #endif
28 #include "mydebug.h"
31 KDebugger::KDebugger(QWidget* parent,
32 ExprWnd* localVars,
33 ExprWnd* watchVars,
34 QListBox* backtrace) :
35 QObject(parent, "debugger"),
36 m_ttyLevel(ttyFull),
37 m_memoryFormat(MDTword | MDThex),
38 m_haveExecutable(false),
39 m_programActive(false),
40 m_programRunning(false),
41 m_sharedLibsListed(false),
42 m_typeTable(0),
43 m_programConfig(0),
44 m_d(0),
45 m_localVariables(*localVars),
46 m_watchVariables(*watchVars),
47 m_btWindow(*backtrace)
49 m_envVars.setAutoDelete(true);
50 m_brkpts.setAutoDelete(true);
52 connect(&m_localVariables, SIGNAL(expanded(QListViewItem*)),
53 SLOT(slotExpanding(QListViewItem*)));
54 connect(&m_watchVariables, SIGNAL(expanded(QListViewItem*)),
55 SLOT(slotExpanding(QListViewItem*)));
56 connect(&m_localVariables, SIGNAL(editValueCommitted(VarTree*, const QString&)),
57 SLOT(slotValueEdited(VarTree*, const QString&)));
58 connect(&m_watchVariables, SIGNAL(editValueCommitted(VarTree*, const QString&)),
59 SLOT(slotValueEdited(VarTree*, const QString&)));
61 connect(&m_btWindow, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
63 emit updateUI();
66 KDebugger::~KDebugger()
68 if (m_programConfig != 0) {
69 saveProgramSettings();
70 m_programConfig->sync();
71 delete m_programConfig;
74 delete m_typeTable;
78 void KDebugger::saveSettings(KConfig* /*config*/)
82 void KDebugger::restoreSettings(KConfig* /*config*/)
87 //////////////////////////////////////////////////////////////////////
88 // external interface
90 const char GeneralGroup[] = "General";
91 const char DebuggerCmdStr[] = "DebuggerCmdStr";
92 const char TTYLevelEntry[] = "TTYLevel";
93 const char KDebugger::DriverNameEntry[] = "DriverName";
95 bool KDebugger::debugProgram(const QString& name,
96 DebuggerDriver* driver)
98 if (m_d != 0 && m_d->isRunning())
100 QApplication::setOverrideCursor(waitCursor);
102 stopDriver();
104 QApplication::restoreOverrideCursor();
106 if (m_d->isRunning() || m_haveExecutable) {
107 /* timed out! We can't really do anything useful now */
108 TRACE("timed out while waiting for gdb to die!");
109 return false;
111 delete m_d;
112 m_d = 0;
115 // wire up the driver
116 connect(driver, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
117 this, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)));
118 connect(driver, SIGNAL(processExited(KProcess*)), SLOT(gdbExited(KProcess*)));
119 connect(driver, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
120 SLOT(parse(CmdQueueItem*,const char*)));
121 connect(driver, SIGNAL(wroteStdin(KProcess*)), SIGNAL(updateUI()));
122 connect(driver, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
123 connect(driver, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
124 connect(driver, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
125 connect(&m_localVariables, SIGNAL(removingItem(VarTree*)),
126 driver, SLOT(dequeueCmdByVar(VarTree*)));
127 connect(&m_watchVariables, SIGNAL(removingItem(VarTree*)),
128 driver, SLOT(dequeueCmdByVar(VarTree*)));
130 // create the program settings object
131 openProgramConfig(name);
133 // get debugger command from per-program settings
134 if (m_programConfig != 0) {
135 m_programConfig->setGroup(GeneralGroup);
136 m_debuggerCmd = readDebuggerCmd();
137 // get terminal emulation level
138 m_ttyLevel = TTYLevel(m_programConfig->readNumEntry(TTYLevelEntry, ttyFull));
140 // the rest is read in later in the handler of DCexecutable
142 m_d = driver;
144 if (!startDriver()) {
145 TRACE("startDriver failed");
146 m_d = 0;
147 return false;
150 TRACE("before file cmd");
151 m_d->executeCmd(DCexecutable, name);
152 m_executable = name;
154 // set remote target
155 if (!m_remoteDevice.isEmpty()) {
156 m_d->executeCmd(DCtargetremote, m_remoteDevice);
157 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
158 m_d->queueCmd(DCframe, 0, DebuggerDriver::QMnormal);
159 m_programActive = true;
160 m_haveExecutable = true;
163 // create a type table
164 m_typeTable = new ProgramTypeTable;
165 m_sharedLibsListed = false;
167 emit updateUI();
169 return true;
172 void KDebugger::shutdown()
174 // shut down debugger driver
175 if (m_d != 0 && m_d->isRunning())
177 stopDriver();
181 void KDebugger::useCoreFile(QString corefile, bool batch)
183 m_corefile = corefile;
184 if (!batch) {
185 CmdQueueItem* cmd = loadCoreFile();
186 cmd->m_byUser = true;
190 void KDebugger::setAttachPid(const QString& pid)
192 m_attachedPid = pid;
195 void KDebugger::programRun()
197 if (!isReady())
198 return;
200 // when program is active, but not a core file, continue
201 // otherwise run the program
202 if (m_programActive && m_corefile.isEmpty()) {
203 // gdb command: continue
204 m_d->executeCmd(DCcont, true);
205 } else {
206 // gdb command: run
207 m_d->executeCmd(DCrun, true);
208 m_corefile = QString();
209 m_programActive = true;
211 m_programRunning = true;
214 void KDebugger::attachProgram(const QString& pid)
216 if (!isReady())
217 return;
219 m_attachedPid = pid;
220 TRACE("Attaching to " + m_attachedPid);
221 m_d->executeCmd(DCattach, m_attachedPid);
222 m_programActive = true;
223 m_programRunning = true;
226 void KDebugger::programRunAgain()
228 if (canSingleStep()) {
229 m_d->executeCmd(DCrun, true);
230 m_corefile = QString();
231 m_programRunning = true;
235 void KDebugger::programStep()
237 if (canSingleStep()) {
238 m_d->executeCmd(DCstep, true);
239 m_programRunning = true;
243 void KDebugger::programNext()
245 if (canSingleStep()) {
246 m_d->executeCmd(DCnext, true);
247 m_programRunning = true;
251 void KDebugger::programStepi()
253 if (canSingleStep()) {
254 m_d->executeCmd(DCstepi, true);
255 m_programRunning = true;
259 void KDebugger::programNexti()
261 if (canSingleStep()) {
262 m_d->executeCmd(DCnexti, true);
263 m_programRunning = true;
267 void KDebugger::programFinish()
269 if (canSingleStep()) {
270 m_d->executeCmd(DCfinish, true);
271 m_programRunning = true;
275 void KDebugger::programKill()
277 if (haveExecutable() && isProgramActive()) {
278 if (m_programRunning) {
279 m_d->interruptInferior();
281 // this is an emergency command; flush queues
282 m_d->flushCommands(true);
283 m_d->executeCmd(DCkill, true);
287 bool KDebugger::runUntil(const QString& fileName, int lineNo)
289 if (isReady() && m_programActive && !m_programRunning) {
290 // strip off directory part of file name
291 QString file = fileName;
292 int offset = file.findRev("/");
293 if (offset >= 0) {
294 file.remove(0, offset+1);
296 m_d->executeCmd(DCuntil, file, lineNo, true);
297 m_programRunning = true;
298 return true;
299 } else {
300 return false;
304 void KDebugger::programBreak()
306 if (m_haveExecutable && m_programRunning) {
307 m_d->interruptInferior();
311 void KDebugger::programArgs(QWidget* parent)
313 if (m_haveExecutable) {
314 QStringList allOptions = m_d->boolOptionList();
315 PgmArgs dlg(parent, m_executable, m_envVars, allOptions);
316 dlg.setArgs(m_programArgs);
317 dlg.setWd(m_programWD);
318 dlg.setOptions(m_boolOptions);
319 if (dlg.exec()) {
320 updateProgEnvironment(dlg.args(), dlg.wd(),
321 dlg.envVars(), dlg.options());
326 void KDebugger::programSettings(QWidget* parent)
328 if (!m_haveExecutable)
329 return;
331 ProgramSettings dlg(parent, m_executable);
333 dlg.m_chooseDriver.setDebuggerCmd(m_debuggerCmd);
334 dlg.m_output.setTTYLevel(m_ttyLevel);
336 if (dlg.exec() == QDialog::Accepted)
338 m_debuggerCmd = dlg.m_chooseDriver.debuggerCmd();
339 m_ttyLevel = TTYLevel(dlg.m_output.ttyLevel());
343 bool KDebugger::setBreakpoint(QString file, int lineNo,
344 const DbgAddr& address, bool temporary)
346 if (!isReady()) {
347 return false;
350 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
351 if (bp == 0)
354 * No such breakpoint, so set a new one. If we have an address, we
355 * set the breakpoint exactly there. Otherwise we use the file name
356 * plus line no.
358 Breakpoint* bp = new Breakpoint;
359 bp->temporary = temporary;
361 if (address.isEmpty())
363 bp->fileName = file;
364 bp->lineNo = lineNo;
366 else
368 bp->address = address;
370 setBreakpoint(bp, false);
372 else
375 * If the breakpoint is disabled, enable it; if it's enabled,
376 * delete that breakpoint.
378 if (bp->enabled) {
379 deleteBreakpoint(bp);
380 } else {
381 enableDisableBreakpoint(bp);
384 return true;
387 void KDebugger::setBreakpoint(Breakpoint* bp, bool queueOnly)
389 CmdQueueItem* cmd;
390 if (!bp->text.isEmpty())
393 * The breakpoint was set using the text box in the breakpoint
394 * list. This is the only way in which watchpoints are set.
396 if (bp->type == Breakpoint::watchpoint) {
397 cmd = m_d->executeCmd(DCwatchpoint, bp->text);
398 } else {
399 cmd = m_d->executeCmd(DCbreaktext, bp->text);
402 else if (bp->address.isEmpty())
404 // strip off directory part of file name
405 QString file = bp->fileName;
406 int offset = file.findRev("/");
407 if (offset >= 0) {
408 file.remove(0, offset+1);
410 if (queueOnly) {
411 cmd = m_d->queueCmd(bp->temporary ? DCtbreakline : DCbreakline,
412 file, bp->lineNo, DebuggerDriver::QMoverride);
413 } else {
414 cmd = m_d->executeCmd(bp->temporary ? DCtbreakline : DCbreakline,
415 file, bp->lineNo);
418 else
420 if (queueOnly) {
421 cmd = m_d->queueCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
422 bp->address.asString(), DebuggerDriver::QMoverride);
423 } else {
424 cmd = m_d->executeCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
425 bp->address.asString());
428 cmd->m_brkpt = bp; // used in newBreakpoint()
431 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo,
432 const DbgAddr& address)
434 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
435 return bp == 0 || enableDisableBreakpoint(bp);
438 bool KDebugger::enableDisableBreakpoint(Breakpoint* bp)
441 * Toggle enabled/disabled state.
443 * The driver is not bothered if we are modifying an orphaned
444 * breakpoint.
446 if (!bp->isOrphaned()) {
447 if (!canChangeBreakpoints()) {
448 return false;
450 m_d->executeCmd(bp->enabled ? DCdisable : DCenable, bp->id);
451 } else {
452 bp->enabled = !bp->enabled;
453 emit breakpointsChanged();
455 return true;
458 bool KDebugger::conditionalBreakpoint(Breakpoint* bp,
459 const QString& condition,
460 int ignoreCount)
463 * Change the condition and ignore count.
465 * The driver is not bothered if we are removing an orphaned
466 * breakpoint.
469 if (!bp->isOrphaned()) {
470 if (!canChangeBreakpoints()) {
471 return false;
474 bool changed = false;
476 if (bp->condition != condition) {
477 // change condition
478 m_d->executeCmd(DCcondition, condition, bp->id);
479 changed = true;
481 if (bp->ignoreCount != ignoreCount) {
482 // change ignore count
483 m_d->executeCmd(DCignore, bp->id, ignoreCount);
484 changed = true;
486 if (changed) {
487 // get the changes
488 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
490 } else {
491 bp->condition = condition;
492 bp->ignoreCount = ignoreCount;
493 emit breakpointsChanged();
495 return true;
498 bool KDebugger::deleteBreakpoint(Breakpoint* bp)
501 * Remove the breakpoint.
503 * The driver is not bothered if we are removing an orphaned
504 * breakpoint.
506 if (!bp->isOrphaned()) {
507 if (!canChangeBreakpoints()) {
508 return false;
510 m_d->executeCmd(DCdelete, bp->id);
511 } else {
512 // move the last entry to bp's slot and shorten the list
513 int i = m_brkpts.findRef(bp);
514 m_brkpts.insert(i, m_brkpts.take(m_brkpts.size()-1));
515 m_brkpts.resize(m_brkpts.size()-1);
516 emit breakpointsChanged();
518 return false;
521 bool KDebugger::canSingleStep()
523 return isReady() && m_programActive && !m_programRunning;
526 bool KDebugger::canChangeBreakpoints()
528 return isReady() && !m_programRunning;
531 bool KDebugger::canStart()
533 return isReady() && !m_programActive;
536 bool KDebugger::isReady() const
538 return m_haveExecutable &&
539 m_d != 0 && m_d->canExecuteImmediately();
542 bool KDebugger::isIdle() const
544 return m_d == 0 || m_d->isIdle();
548 //////////////////////////////////////////////////////////
549 // debugger driver
551 bool KDebugger::startDriver()
553 emit debuggerStarting(); /* must set m_inferiorTerminal */
556 * If the per-program command string is empty, use the global setting
557 * (which might also be empty, in which case the driver uses its
558 * default).
560 m_explicitKill = false;
561 if (!m_d->startup(m_debuggerCmd)) {
562 return false;
566 * If we have an output terminal, we use it. Otherwise we will run the
567 * program with input and output redirected to /dev/null. Other
568 * redirections are also necessary depending on the tty emulation
569 * level.
571 int redirect = RDNstdin|RDNstdout|RDNstderr; /* redirect everything */
572 if (!m_inferiorTerminal.isEmpty()) {
573 switch (m_ttyLevel) {
574 default:
575 case ttyNone:
576 // redirect everything
577 break;
578 case ttySimpleOutputOnly:
579 redirect = RDNstdin;
580 break;
581 case ttyFull:
582 redirect = 0;
583 break;
586 m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
588 return true;
591 void KDebugger::stopDriver()
593 m_explicitKill = true;
595 if (m_attachedPid.isEmpty()) {
596 m_d->terminate();
597 } else {
598 m_d->detachAndTerminate();
602 * We MUST wait until the slot gdbExited() has been called. But to
603 * avoid a deadlock, we wait only for some certain maximum time. Should
604 * this timeout be reached, the only reasonable thing one could do then
605 * is exiting kdbg.
607 kapp->processEvents(1000); /* ideally, this will already shut it down */
608 int maxTime = 20; /* about 20 seconds */
609 while (m_haveExecutable && maxTime > 0) {
610 // give gdb time to die (and send a SIGCLD)
611 ::sleep(1);
612 --maxTime;
613 kapp->processEvents(1000);
617 void KDebugger::gdbExited(KProcess*)
620 * Save settings, but only if gdb has already processed "info line
621 * main", otherwise we would save an empty config file, because it
622 * isn't read in until then!
624 if (m_programConfig != 0) {
625 if (m_haveExecutable) {
626 saveProgramSettings();
627 m_programConfig->sync();
629 delete m_programConfig;
630 m_programConfig = 0;
633 // erase types
634 delete m_typeTable;
635 m_typeTable = 0;
637 if (m_explicitKill) {
638 TRACE(m_d->driverName() + " exited normally");
639 } else {
640 QString msg = i18n("%1 exited unexpectedly.\n"
641 "Restart the session (e.g. with File|Executable).");
642 KMessageBox::error(parentWidget(), msg.arg(m_d->driverName()));
645 // reset state
646 m_haveExecutable = false;
647 m_executable = "";
648 m_programActive = false;
649 m_programRunning = false;
650 m_explicitKill = false;
651 m_debuggerCmd = QString(); /* use global setting at next start! */
652 m_attachedPid = QString(); /* we are no longer attached to a process */
653 m_ttyLevel = ttyFull;
654 m_brkpts.clear();
656 // erase PC
657 emit updatePC(QString(), -1, DbgAddr(), 0);
660 QString KDebugger::getConfigForExe(const QString& name)
662 QFileInfo fi(name);
663 QString pgmConfigFile = fi.dirPath(true);
664 if (!pgmConfigFile.isEmpty()) {
665 pgmConfigFile += '/';
667 pgmConfigFile += ".kdbgrc." + fi.fileName();
668 TRACE("program config file = " + pgmConfigFile);
669 return pgmConfigFile;
672 void KDebugger::openProgramConfig(const QString& name)
674 ASSERT(m_programConfig == 0);
676 QString pgmConfigFile = getConfigForExe(name);
678 m_programConfig = new ProgramConfig(pgmConfigFile);
681 const char EnvironmentGroup[] = "Environment";
682 const char WatchGroup[] = "Watches";
683 const char FileVersion[] = "FileVersion";
684 const char ProgramArgs[] = "ProgramArgs";
685 const char WorkingDirectory[] = "WorkingDirectory";
686 const char OptionsSelected[] = "OptionsSelected";
687 const char Variable[] = "Var%d";
688 const char Value[] = "Value%d";
689 const char ExprFmt[] = "Expr%d";
691 void KDebugger::saveProgramSettings()
693 ASSERT(m_programConfig != 0);
694 m_programConfig->setGroup(GeneralGroup);
695 m_programConfig->writeEntry(FileVersion, 1);
696 m_programConfig->writeEntry(ProgramArgs, m_programArgs);
697 m_programConfig->writeEntry(WorkingDirectory, m_programWD);
698 m_programConfig->writeEntry(OptionsSelected, m_boolOptions);
699 m_programConfig->writeEntry(DebuggerCmdStr, m_debuggerCmd);
700 m_programConfig->writeEntry(TTYLevelEntry, int(m_ttyLevel));
701 QString driverName;
702 if (m_d != 0)
703 driverName = m_d->driverName();
704 m_programConfig->writeEntry(DriverNameEntry, driverName);
706 // write environment variables
707 m_programConfig->deleteGroup(EnvironmentGroup);
708 m_programConfig->setGroup(EnvironmentGroup);
709 QDictIterator<EnvVar> it = m_envVars;
710 EnvVar* var;
711 QString varName;
712 QString varValue;
713 for (int i = 0; (var = it) != 0; ++it, ++i) {
714 varName.sprintf(Variable, i);
715 varValue.sprintf(Value, i);
716 m_programConfig->writeEntry(varName, it.currentKey());
717 m_programConfig->writeEntry(varValue, var->value);
720 saveBreakpoints(m_programConfig);
722 // watch expressions
723 // first get rid of whatever was in this group
724 m_programConfig->deleteGroup(WatchGroup);
725 // then start a new group
726 m_programConfig->setGroup(WatchGroup);
727 VarTree* item = m_watchVariables.firstChild();
728 int watchNum = 0;
729 for (; item != 0; item = item->nextSibling(), ++watchNum) {
730 varName.sprintf(ExprFmt, watchNum);
731 m_programConfig->writeEntry(varName, item->getText());
734 // give others a chance
735 emit saveProgramSpecific(m_programConfig);
738 void KDebugger::overrideProgramArguments(const QString& args)
740 ASSERT(m_programConfig != 0);
741 m_programConfig->setGroup(GeneralGroup);
742 m_programConfig->writeEntry(ProgramArgs, args);
745 void KDebugger::restoreProgramSettings()
747 ASSERT(m_programConfig != 0);
748 m_programConfig->setGroup(GeneralGroup);
750 * We ignore file version for now we will use it in the future to
751 * distinguish different versions of this configuration file.
753 // m_debuggerCmd has been read in already
754 // m_ttyLevel has been read in already
755 QString pgmArgs = m_programConfig->readEntry(ProgramArgs);
756 QString pgmWd = m_programConfig->readEntry(WorkingDirectory);
757 QStringList boolOptions = m_programConfig->readListEntry(OptionsSelected);
758 m_boolOptions = QStringList();
760 // read environment variables
761 m_programConfig->setGroup(EnvironmentGroup);
762 m_envVars.clear();
763 QDict<EnvVar> pgmVars;
764 EnvVar* var;
765 QString varName;
766 QString varValue;
767 for (int i = 0;; ++i) {
768 varName.sprintf(Variable, i);
769 varValue.sprintf(Value, i);
770 if (!m_programConfig->hasKey(varName)) {
771 /* entry not present, assume that we've hit them all */
772 break;
774 QString name = m_programConfig->readEntry(varName);
775 if (name.isEmpty()) {
776 // skip empty names
777 continue;
779 var = new EnvVar;
780 var->value = m_programConfig->readEntry(varValue);
781 var->status = EnvVar::EVnew;
782 pgmVars.insert(name, var);
785 updateProgEnvironment(pgmArgs, pgmWd, pgmVars, boolOptions);
787 restoreBreakpoints(m_programConfig);
789 // watch expressions
790 m_programConfig->setGroup(WatchGroup);
791 m_watchVariables.clear();
792 for (int i = 0;; ++i) {
793 varName.sprintf(ExprFmt, i);
794 if (!m_programConfig->hasKey(varName)) {
795 /* entry not present, assume that we've hit them all */
796 break;
798 QString expr = m_programConfig->readEntry(varName);
799 if (expr.isEmpty()) {
800 // skip empty expressions
801 continue;
803 addWatch(expr);
806 // give others a chance
807 emit restoreProgramSpecific(m_programConfig);
811 * Reads the debugger command line from the program settings. The config
812 * group must have been set by the caller.
814 QString KDebugger::readDebuggerCmd()
816 QString debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
818 // always let the user confirm the debugger cmd if we are root
819 if (::geteuid() == 0)
821 if (!debuggerCmd.isEmpty()) {
822 QString msg = i18n(
823 "The settings for this program specify "
824 "the following debugger command:\n%1\n"
825 "Shall this command be used?");
826 if (KMessageBox::warningYesNo(parentWidget(), msg.arg(debuggerCmd))
827 != KMessageBox::Yes)
829 // don't use it
830 debuggerCmd = QString();
834 return debuggerCmd;
838 * Breakpoints are saved one per group.
840 const char BPGroup[] = "Breakpoint %d";
841 const char File[] = "File";
842 const char Line[] = "Line";
843 const char Text[] = "Text";
844 const char Address[] = "Address";
845 const char Temporary[] = "Temporary";
846 const char Enabled[] = "Enabled";
847 const char Condition[] = "Condition";
849 void KDebugger::saveBreakpoints(ProgramConfig* config)
851 QString groupName;
852 int i = 0;
853 for (uint j = 0; j < m_brkpts.size(); j++) {
854 Breakpoint* bp = m_brkpts[j];
855 if (bp->type == Breakpoint::watchpoint)
856 continue; /* don't save watchpoints */
857 groupName.sprintf(BPGroup, i++);
859 /* remove remmants */
860 config->deleteGroup(groupName);
862 config->setGroup(groupName);
863 if (!bp->text.isEmpty()) {
865 * The breakpoint was set using the text box in the breakpoint
866 * list. We do not save the location by filename+line number,
867 * but instead honor what the user typed (a function name, for
868 * example, which could move between sessions).
870 config->writeEntry(Text, bp->text);
871 } else if (!bp->fileName.isEmpty()) {
872 config->writeEntry(File, bp->fileName);
873 config->writeEntry(Line, bp->lineNo);
875 * Addresses are hardly correct across sessions, so we don't
876 * save it.
878 } else {
879 config->writeEntry(Address, bp->address.asString());
881 config->writeEntry(Temporary, bp->temporary);
882 config->writeEntry(Enabled, bp->enabled);
883 if (!bp->condition.isEmpty())
884 config->writeEntry(Condition, bp->condition);
885 // we do not save the ignore count
887 // delete remaining groups
888 // we recognize that a group is present if there is an Enabled entry
889 for (;; i++) {
890 groupName.sprintf(BPGroup, i);
891 config->setGroup(groupName);
892 if (!config->hasKey(Enabled)) {
893 /* group not present, assume that we've hit them all */
894 break;
896 config->deleteGroup(groupName);
900 void KDebugger::restoreBreakpoints(ProgramConfig* config)
902 QString groupName;
904 * We recognize the end of the list if there is no Enabled entry
905 * present.
907 for (int i = 0;; i++) {
908 groupName.sprintf(BPGroup, i);
909 config->setGroup(groupName);
910 if (!config->hasKey(Enabled)) {
911 /* group not present, assume that we've hit them all */
912 break;
914 Breakpoint* bp = new Breakpoint;
915 bp->fileName = config->readEntry(File);
916 bp->lineNo = config->readNumEntry(Line, -1);
917 bp->text = config->readEntry(Text);
918 bp->address = config->readEntry(Address);
919 // check consistency
920 if ((bp->fileName.isEmpty() || bp->lineNo < 0) &&
921 bp->text.isEmpty() &&
922 bp->address.isEmpty())
924 delete bp;
925 continue;
927 bp->enabled = config->readBoolEntry(Enabled, true);
928 bp->temporary = config->readBoolEntry(Temporary, false);
929 bp->condition = config->readEntry(Condition);
932 * Add the breakpoint.
934 setBreakpoint(bp, false);
935 // the new breakpoint is disabled or conditionalized later
936 // in newBreakpoint()
938 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
942 // parse output of command cmd
943 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
945 ASSERT(cmd != 0); /* queue mustn't be empty */
947 TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
949 switch (cmd->m_cmd) {
950 case DCtargetremote:
951 // the output (if any) is uninteresting
952 case DCsetargs:
953 case DCtty:
954 // there is no output
955 case DCsetenv:
956 case DCunsetenv:
957 case DCsetoption:
958 /* if value is empty, we see output, but we don't care */
959 break;
960 case DCcd:
961 /* display gdb's message in the status bar */
962 m_d->parseChangeWD(output, m_statusMessage);
963 emit updateStatusMessage();
964 break;
965 case DCinitialize:
966 break;
967 case DCexecutable:
968 if (m_d->parseChangeExecutable(output, m_statusMessage))
970 // success; restore breakpoints etc.
971 if (m_programConfig != 0) {
972 restoreProgramSettings();
974 // load file containing main() or core file
975 if (!m_corefile.isEmpty())
977 // load core file
978 loadCoreFile();
980 else if (!m_attachedPid.isEmpty())
982 m_d->queueCmd(DCattach, m_attachedPid, DebuggerDriver::QMoverride);
983 m_programActive = true;
984 m_programRunning = true;
986 else if (!m_remoteDevice.isEmpty())
988 // handled elsewhere
990 else
992 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
994 if (!m_statusMessage.isEmpty())
995 emit updateStatusMessage();
996 } else {
997 QString msg = m_d->driverName() + ": " + m_statusMessage;
998 KMessageBox::sorry(parentWidget(), msg);
999 m_executable = "";
1000 m_corefile = ""; /* don't process core file */
1001 m_haveExecutable = false;
1003 break;
1004 case DCcorefile:
1005 // in any event we have an executable at this point
1006 m_haveExecutable = true;
1007 if (m_d->parseCoreFile(output)) {
1008 // loading a core is like stopping at a breakpoint
1009 m_programActive = true;
1010 handleRunCommands(output);
1011 // do not reset m_corefile
1012 } else {
1013 // report error
1014 QString msg = m_d->driverName() + ": " + QString(output);
1015 KMessageBox::sorry(parentWidget(), msg);
1017 // if core file was loaded from command line, revert to info line main
1018 if (!cmd->m_byUser) {
1019 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
1021 m_corefile = QString(); /* core file not available any more */
1023 break;
1024 case DCinfolinemain:
1025 // ignore the output, marked file info follows
1026 m_haveExecutable = true;
1027 break;
1028 case DCinfolocals:
1029 // parse local variables
1030 if (output[0] != '\0') {
1031 handleLocals(output);
1033 break;
1034 case DCinforegisters:
1035 handleRegisters(output);
1036 break;
1037 case DCexamine:
1038 handleMemoryDump(output);
1039 break;
1040 case DCinfoline:
1041 handleInfoLine(cmd, output);
1042 break;
1043 case DCdisassemble:
1044 handleDisassemble(cmd, output);
1045 break;
1046 case DCframe:
1047 handleFrameChange(output);
1048 updateAllExprs();
1049 break;
1050 case DCbt:
1051 handleBacktrace(output);
1052 updateAllExprs();
1053 break;
1054 case DCprint:
1055 handlePrint(cmd, output);
1056 break;
1057 case DCprintDeref:
1058 handlePrintDeref(cmd, output);
1059 break;
1060 case DCattach:
1061 m_haveExecutable = true;
1062 // fall through
1063 case DCrun:
1064 case DCcont:
1065 case DCstep:
1066 case DCstepi:
1067 case DCnext:
1068 case DCnexti:
1069 case DCfinish:
1070 case DCuntil:
1071 case DCthread:
1072 handleRunCommands(output);
1073 break;
1074 case DCkill:
1075 m_programRunning = m_programActive = false;
1076 // erase PC
1077 emit updatePC(QString(), -1, DbgAddr(), 0);
1078 break;
1079 case DCbreaktext:
1080 case DCbreakline:
1081 case DCtbreakline:
1082 case DCbreakaddr:
1083 case DCtbreakaddr:
1084 case DCwatchpoint:
1085 newBreakpoint(cmd, output);
1086 // fall through
1087 case DCdelete:
1088 case DCenable:
1089 case DCdisable:
1090 // these commands need immediate response
1091 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverrideMoreEqual);
1092 break;
1093 case DCinfobreak:
1094 // note: this handler must not enqueue a command, since
1095 // DCinfobreak is used at various different places.
1096 updateBreakList(output);
1097 break;
1098 case DCfindType:
1099 handleFindType(cmd, output);
1100 break;
1101 case DCprintStruct:
1102 case DCprintQStringStruct:
1103 case DCprintWChar:
1104 handlePrintStruct(cmd, output);
1105 break;
1106 case DCinfosharedlib:
1107 handleSharedLibs(output);
1108 break;
1109 case DCcondition:
1110 case DCignore:
1111 // we are not interested in the output
1112 break;
1113 case DCinfothreads:
1114 handleThreadList(output);
1115 break;
1116 case DCsetpc:
1117 handleSetPC(output);
1118 break;
1119 case DCsetvariable:
1120 handleSetVariable(cmd, output);
1121 break;
1125 void KDebugger::backgroundUpdate()
1128 * If there are still expressions that need to be updated, then do so.
1130 if (m_programActive)
1131 evalExpressions();
1134 void KDebugger::handleRunCommands(const char* output)
1136 uint flags = m_d->parseProgramStopped(output, m_statusMessage);
1137 emit updateStatusMessage();
1139 m_programActive = flags & DebuggerDriver::SFprogramActive;
1141 // refresh files if necessary
1142 if (flags & DebuggerDriver::SFrefreshSource) {
1143 TRACE("re-reading files");
1144 emit executableUpdated();
1148 * Try to set any orphaned breakpoints now.
1150 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1151 if (m_brkpts[i]->isOrphaned()) {
1152 TRACE("re-trying brkpt loc: "+m_brkpts[i]->location+
1153 " file: "+m_brkpts[i]->fileName+
1154 QString().sprintf(" line: %d", m_brkpts[i]->lineNo));
1155 setBreakpoint(m_brkpts[i], true);
1156 flags |= DebuggerDriver::SFrefreshBreak;
1161 * If we stopped at a breakpoint, we must update the breakpoint list
1162 * because the hit count changes. Also, if the breakpoint was temporary
1163 * it would go away now.
1165 if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
1166 stopMayChangeBreakList())
1168 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
1172 * If we haven't listed the shared libraries yet, do so. We must do
1173 * this before we emit any commands that list variables, since the type
1174 * libraries depend on the shared libraries.
1176 if (!m_sharedLibsListed) {
1177 // must be a high-priority command!
1178 m_d->executeCmd(DCinfosharedlib);
1181 // get the backtrace if the program is running
1182 if (m_programActive) {
1183 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
1184 } else {
1185 // program finished: erase PC
1186 emit updatePC(QString(), -1, DbgAddr(), 0);
1187 // dequeue any commands in the queues
1188 m_d->flushCommands();
1191 /* Update threads list */
1192 if (m_programActive && (flags & DebuggerDriver::SFrefreshThreads)) {
1193 m_d->queueCmd(DCinfothreads, DebuggerDriver::QMoverride);
1196 m_programRunning = false;
1197 emit programStopped();
1200 void KDebugger::slotInferiorRunning()
1202 m_programRunning = true;
1205 void KDebugger::updateAllExprs()
1207 if (!m_programActive)
1208 return;
1210 // retrieve local variables
1211 m_d->queueCmd(DCinfolocals, DebuggerDriver::QMoverride);
1213 // retrieve registers
1214 m_d->queueCmd(DCinforegisters, DebuggerDriver::QMoverride);
1216 // get new memory dump
1217 if (!m_memoryExpression.isEmpty()) {
1218 queueMemoryDump(false);
1221 // update watch expressions
1222 VarTree* item = m_watchVariables.firstChild();
1223 for (; item != 0; item = item->nextSibling()) {
1224 m_watchEvalExpr.push_back(item->getText());
1228 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
1229 const QDict<EnvVar>& newVars,
1230 const QStringList& newOptions)
1232 m_programArgs = args;
1233 m_d->executeCmd(DCsetargs, m_programArgs);
1234 TRACE("new pgm args: " + m_programArgs + "\n");
1236 m_programWD = wd.stripWhiteSpace();
1237 if (!m_programWD.isEmpty()) {
1238 m_d->executeCmd(DCcd, m_programWD);
1239 TRACE("new wd: " + m_programWD + "\n");
1242 // update environment variables
1243 QDictIterator<EnvVar> it = newVars;
1244 EnvVar* val;
1245 for (; (val = it) != 0; ++it) {
1246 QString var = it.currentKey();
1247 switch (val->status) {
1248 case EnvVar::EVnew:
1249 m_envVars.insert(var, val);
1250 // fall thru
1251 case EnvVar::EVdirty:
1252 // the value must be in our list
1253 ASSERT(m_envVars[var] == val);
1254 // update value
1255 m_d->executeCmd(DCsetenv, var, val->value);
1256 break;
1257 case EnvVar::EVdeleted:
1258 // must be in our list
1259 ASSERT(m_envVars[var] == val);
1260 // delete value
1261 m_d->executeCmd(DCunsetenv, var);
1262 m_envVars.remove(var);
1263 break;
1264 default:
1265 ASSERT(false);
1266 case EnvVar::EVclean:
1267 // variable not changed
1268 break;
1272 // update options
1273 QStringList::ConstIterator oi;
1274 for (oi = newOptions.begin(); oi != newOptions.end(); ++oi)
1276 if (m_boolOptions.findIndex(*oi) < 0) {
1277 // the options is currently not set, so set it
1278 m_d->executeCmd(DCsetoption, *oi, 1);
1279 } else {
1280 // option is set, no action required, but move it to the end
1281 m_boolOptions.remove(*oi);
1283 m_boolOptions.append(*oi);
1286 * Now all options that should be set are at the end of m_boolOptions.
1287 * If some options need to be unset, they are at the front of the list.
1288 * Here we unset and remove them.
1290 while (m_boolOptions.count() > newOptions.count()) {
1291 m_d->executeCmd(DCsetoption, m_boolOptions.first(), 0);
1292 m_boolOptions.remove(m_boolOptions.begin());
1296 void KDebugger::handleLocals(const char* output)
1298 // retrieve old list of local variables
1299 QStrList oldVars;
1300 m_localVariables.exprList(oldVars);
1303 * Get local variables.
1305 QList<ExprValue> newVars;
1306 parseLocals(output, newVars);
1309 * Clear any old VarTree item pointers, so that later we don't access
1310 * dangling pointers.
1312 m_localVariables.clearPendingUpdates();
1315 * Match old variables against new ones.
1317 for (const char* n = oldVars.first(); n != 0; n = oldVars.next()) {
1318 // lookup this variable in the list of new variables
1319 ExprValue* v = newVars.first();
1320 while (v != 0 && v->m_name != n) {
1321 v = newVars.next();
1323 if (v == 0) {
1324 // old variable not in the new variables
1325 TRACE(QString("old var deleted: ") + n);
1326 VarTree* v = m_localVariables.topLevelExprByName(n);
1327 if (v != 0) {
1328 m_localVariables.removeExpr(v);
1330 } else {
1331 // variable in both old and new lists: update
1332 TRACE(QString("update var: ") + n);
1333 m_localVariables.updateExpr(newVars.current(), *m_typeTable);
1334 // remove the new variable from the list
1335 newVars.remove();
1336 delete v;
1339 // insert all remaining new variables
1340 while (!newVars.isEmpty())
1342 ExprValue* v = newVars.take(0);
1343 TRACE("new var: " + v->m_name);
1344 m_localVariables.insertExpr(v, *m_typeTable);
1345 delete v;
1349 void KDebugger::parseLocals(const char* output, QList<ExprValue>& newVars)
1351 QList<ExprValue> vars;
1352 m_d->parseLocals(output, vars);
1354 QString origName; /* used in renaming variables */
1355 while (vars.count() > 0)
1357 ExprValue* variable = vars.take(0);
1359 * When gdb prints local variables, those from the innermost block
1360 * come first. We run through the list of already parsed variables
1361 * to find duplicates (ie. variables that hide local variables from
1362 * a surrounding block). We keep the name of the inner variable, but
1363 * rename those from the outer block so that, when the value is
1364 * updated in the window, the value of the variable that is
1365 * _visible_ changes the color!
1367 int block = 0;
1368 origName = variable->m_name;
1369 for (ExprValue* v = newVars.first(); v != 0; v = newVars.next()) {
1370 if (variable->m_name == v->m_name) {
1371 // we found a duplicate, change name
1372 block++;
1373 QString newName = origName + " (" + QString().setNum(block) + ")";
1374 variable->m_name = newName;
1377 newVars.append(variable);
1381 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1383 ASSERT(cmd->m_expr != 0);
1385 ExprValue* variable = m_d->parsePrintExpr(output, true);
1386 if (variable == 0)
1387 return false;
1389 // set expression "name"
1390 variable->m_name = cmd->m_expr->getText();
1393 TRACE("update expr: " + cmd->m_expr->getText());
1394 cmd->m_exprWnd->updateExpr(cmd->m_expr, variable, *m_typeTable);
1395 delete variable;
1398 evalExpressions(); /* enqueue dereferenced pointers */
1400 return true;
1403 bool KDebugger::handlePrintDeref(CmdQueueItem* cmd, const char* output)
1405 ASSERT(cmd->m_expr != 0);
1407 ExprValue* variable = m_d->parsePrintExpr(output, true);
1408 if (variable == 0)
1409 return false;
1411 // set expression "name"
1412 variable->m_name = cmd->m_expr->getText();
1416 * We must insert a dummy parent, because otherwise variable's value
1417 * would overwrite cmd->m_expr's value.
1419 ExprValue* dummyParent = new ExprValue(variable->m_name, VarTree::NKplain);
1420 dummyParent->m_varKind = VarTree::VKdummy;
1421 // the name of the parsed variable is the address of the pointer
1422 QString addr = "*" + cmd->m_expr->value();
1423 variable->m_name = addr;
1424 variable->m_nameKind = VarTree::NKaddress;
1426 dummyParent->m_child = variable;
1427 // expand the first level for convenience
1428 variable->m_initiallyExpanded = true;
1429 TRACE("update ptr: " + cmd->m_expr->getText());
1430 cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent, *m_typeTable);
1431 delete dummyParent;
1434 evalExpressions(); /* enqueue dereferenced pointers */
1436 return true;
1439 // parse the output of bt
1440 void KDebugger::handleBacktrace(const char* output)
1442 // reduce flicker
1443 m_btWindow.setAutoUpdate(false);
1445 m_btWindow.clear();
1447 QList<StackFrame> stack;
1448 m_d->parseBackTrace(output, stack);
1450 if (stack.count() > 0) {
1451 StackFrame* frm = stack.take(0);
1452 // first frame must set PC
1453 // note: frm->lineNo is zero-based
1454 emit updatePC(frm->fileName, frm->lineNo, frm->address, frm->frameNo);
1456 do {
1457 QString func;
1458 if (frm->var != 0)
1459 func = frm->var->m_name;
1460 else
1461 func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1462 m_btWindow.insertItem(func);
1463 TRACE("frame " + func + " (" + frm->fileName + ":" +
1464 QString().setNum(frm->lineNo+1) + ")");
1465 delete frm;
1467 while ((frm = stack.take()) != 0);
1470 m_btWindow.setAutoUpdate(true);
1471 m_btWindow.repaint();
1474 void KDebugger::gotoFrame(int frame)
1476 m_d->executeCmd(DCframe, frame);
1479 void KDebugger::handleFrameChange(const char* output)
1481 QString fileName;
1482 int frameNo;
1483 int lineNo;
1484 DbgAddr address;
1485 if (m_d->parseFrameChange(output, frameNo, fileName, lineNo, address)) {
1486 /* lineNo can be negative here if we can't find a file name */
1487 emit updatePC(fileName, lineNo, address, frameNo);
1488 } else {
1489 emit updatePC(fileName, -1, address, frameNo);
1493 void KDebugger::evalExpressions()
1495 // evaluate expressions in the following order:
1496 // watch expressions
1497 // pointers in local variables
1498 // pointers in watch expressions
1499 // types in local variables
1500 // types in watch expressions
1501 // struct members in local variables
1502 // struct members in watch expressions
1503 VarTree* exprItem = 0;
1504 if (!m_watchEvalExpr.empty())
1506 QString expr = m_watchEvalExpr.front();
1507 m_watchEvalExpr.pop_front();
1508 exprItem = m_watchVariables.topLevelExprByName(expr);
1510 if (exprItem != 0) {
1511 CmdQueueItem* cmd = m_d->queueCmd(DCprint, exprItem->getText(), DebuggerDriver::QMoverride);
1512 // remember which expr this was
1513 cmd->m_expr = exprItem;
1514 cmd->m_exprWnd = &m_watchVariables;
1515 } else {
1516 ExprWnd* wnd;
1517 #define POINTER(widget) \
1518 wnd = &widget; \
1519 exprItem = widget.nextUpdatePtr(); \
1520 if (exprItem != 0) goto pointer
1521 #define STRUCT(widget) \
1522 wnd = &widget; \
1523 exprItem = widget.nextUpdateStruct(); \
1524 if (exprItem != 0) goto ustruct
1525 #define TYPE(widget) \
1526 wnd = &widget; \
1527 exprItem = widget.nextUpdateType(); \
1528 if (exprItem != 0) goto type
1529 repeat:
1530 POINTER(m_localVariables);
1531 POINTER(m_watchVariables);
1532 STRUCT(m_localVariables);
1533 STRUCT(m_watchVariables);
1534 TYPE(m_localVariables);
1535 TYPE(m_watchVariables);
1536 #undef POINTER
1537 #undef STRUCT
1538 #undef TYPE
1539 return;
1541 pointer:
1542 // we have an expression to send
1543 dereferencePointer(wnd, exprItem, false);
1544 return;
1546 ustruct:
1547 // paranoia
1548 if (exprItem->m_type == 0 || exprItem->m_type == TypeInfo::unknownType())
1549 goto repeat;
1550 evalInitialStructExpression(exprItem, wnd, false);
1551 return;
1553 type:
1555 * Sometimes a VarTree gets registered twice for a type update. So
1556 * it may happen that it has already been updated. Hence, we ignore
1557 * it here and go on to the next task.
1559 if (exprItem->m_type != 0)
1560 goto repeat;
1561 determineType(wnd, exprItem);
1565 void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem,
1566 bool immediate)
1568 ASSERT(exprItem->m_varKind == VarTree::VKpointer);
1570 QString expr = exprItem->computeExpr();
1571 TRACE("dereferencing pointer: " + expr);
1572 CmdQueueItem* cmd;
1573 if (immediate) {
1574 cmd = m_d->queueCmd(DCprintDeref, expr, DebuggerDriver::QMoverrideMoreEqual);
1575 } else {
1576 cmd = m_d->queueCmd(DCprintDeref, expr, DebuggerDriver::QMoverride);
1578 // remember which expr this was
1579 cmd->m_expr = exprItem;
1580 cmd->m_exprWnd = wnd;
1583 void KDebugger::determineType(ExprWnd* wnd, VarTree* exprItem)
1585 ASSERT(exprItem->m_varKind == VarTree::VKstruct);
1587 QString expr = exprItem->computeExpr();
1588 TRACE("get type of: " + expr);
1589 CmdQueueItem* cmd;
1590 cmd = m_d->queueCmd(DCfindType, expr, DebuggerDriver::QMoverride);
1592 // remember which expr this was
1593 cmd->m_expr = exprItem;
1594 cmd->m_exprWnd = wnd;
1597 void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output)
1599 QString type;
1600 if (m_d->parseFindType(output, type))
1602 ASSERT(cmd != 0 && cmd->m_expr != 0);
1604 TypeInfo* info = m_typeTable->lookup(type);
1606 if (info == 0) {
1608 * We've asked gdb for the type of the expression in
1609 * cmd->m_expr, but it returned a name we don't know. The base
1610 * class (and member) types have been checked already (at the
1611 * time when we parsed that particular expression). Now it's
1612 * time to derive the type from the base classes as a last
1613 * resort.
1615 info = cmd->m_expr->inferTypeFromBaseClass();
1616 // if we found a type through this method, register an alias
1617 if (info != 0) {
1618 TRACE("infered alias: " + type);
1619 m_typeTable->registerAlias(type, info);
1622 if (info == 0) {
1623 TRACE("unknown type "+type);
1624 cmd->m_expr->m_type = TypeInfo::unknownType();
1625 } else {
1626 cmd->m_expr->m_type = info;
1627 /* since this node has a new type, we get its value immediately */
1628 evalInitialStructExpression(cmd->m_expr, cmd->m_exprWnd, false);
1629 return;
1633 evalExpressions(); /* queue more of them */
1636 void KDebugger::handlePrintStruct(CmdQueueItem* cmd, const char* output)
1638 VarTree* var = cmd->m_expr;
1639 ASSERT(var != 0);
1640 ASSERT(var->m_varKind == VarTree::VKstruct);
1642 ExprValue* partExpr;
1643 if (cmd->m_cmd == DCprintQStringStruct) {
1644 partExpr = m_d->parseQCharArray(output, false, m_typeTable->qCharIsShort());
1645 } else if (cmd->m_cmd == DCprintWChar) {
1646 partExpr = m_d->parseQCharArray(output, false, true);
1647 } else {
1648 partExpr = m_d->parsePrintExpr(output, false);
1650 bool errorValue =
1651 partExpr == 0 ||
1652 /* we only allow simple values at the moment */
1653 partExpr->m_child != 0;
1655 QString partValue;
1656 if (errorValue)
1658 partValue = "?""?""?"; // 2 question marks in a row would be a trigraph
1659 } else {
1660 partValue = partExpr->m_value;
1662 delete partExpr;
1663 partExpr = 0;
1666 * Updating a struct value works like this: var->m_partialValue holds
1667 * the value that we have gathered so far (it's been initialized with
1668 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1669 * we append the printed result followed by the next
1670 * var->m_type->m_displayString to var->m_partialValue.
1672 * If the expression we just evaluated was a guard expression, and it
1673 * resulted in an error, we must not evaluate the real expression, but
1674 * go on to the next index. (We must still add the question marks to
1675 * the value).
1677 * Next, if this was the length expression, we still have not seen the
1678 * real expression, but the length of a QString.
1680 ASSERT(var->m_exprIndex >= 0 && var->m_exprIndex <= typeInfoMaxExpr);
1682 if (errorValue || !var->m_exprIndexUseGuard)
1684 // add current partValue (which might be the question marks)
1685 var->m_partialValue += partValue;
1686 var->m_exprIndex++; /* next part */
1687 var->m_exprIndexUseGuard = true;
1688 var->m_partialValue += var->m_type->m_displayString[var->m_exprIndex];
1690 else
1692 // this was a guard expression that succeeded
1693 // go for the real expression
1694 var->m_exprIndexUseGuard = false;
1697 /* go for more sub-expressions if needed */
1698 if (var->m_exprIndex < var->m_type->m_numExprs) {
1699 /* queue a new print command with quite high priority */
1700 evalStructExpression(var, cmd->m_exprWnd, true);
1701 return;
1704 cmd->m_exprWnd->updateStructValue(var);
1706 evalExpressions(); /* enqueue dereferenced pointers */
1709 /* queues the first printStruct command for a struct */
1710 void KDebugger::evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1712 var->m_exprIndex = 0;
1713 if (var->m_type != TypeInfo::wchartType())
1715 var->m_exprIndexUseGuard = true;
1716 var->m_partialValue = var->m_type->m_displayString[0];
1717 evalStructExpression(var, wnd, immediate);
1719 else
1721 var->m_exprIndexUseGuard = false;
1722 QString expr = var->computeExpr();
1723 CmdQueueItem* cmd = m_d->queueCmd(DCprintWChar, expr,
1724 immediate ? DebuggerDriver::QMoverrideMoreEqual
1725 : DebuggerDriver::QMoverride);
1726 // remember which expression this was
1727 cmd->m_expr = var;
1728 cmd->m_exprWnd = wnd;
1732 /** queues a printStruct command; var must have been initialized correctly */
1733 void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1735 QString base = var->computeExpr();
1736 QString exprFmt;
1737 if (var->m_exprIndexUseGuard) {
1738 exprFmt = var->m_type->m_guardStrings[var->m_exprIndex];
1739 if (exprFmt.isEmpty()) {
1740 // no guard, omit it and go to expression
1741 var->m_exprIndexUseGuard = false;
1744 if (!var->m_exprIndexUseGuard) {
1745 exprFmt = var->m_type->m_exprStrings[var->m_exprIndex];
1748 QString expr;
1749 expr.sprintf(exprFmt, base.data());
1751 DbgCommand dbgCmd = DCprintStruct;
1752 // check if this is a QString::Data
1753 if (strncmp(expr, "/QString::Data ", 15) == 0)
1755 if (m_typeTable->parseQt2QStrings())
1757 expr = expr.mid(15, expr.length()); /* strip off /QString::Data */
1758 dbgCmd = DCprintQStringStruct;
1759 } else {
1761 * This should not happen: the type libraries should be set up
1762 * in a way that this can't happen. If this happens
1763 * nevertheless it means that, eg., kdecore was loaded but qt2
1764 * was not (only qt2 enables the QString feature).
1766 // TODO: remove this "print"; queue the next printStruct instead
1767 expr = "*0";
1769 } else {
1770 expr = expr;
1772 TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1773 CmdQueueItem* cmd = m_d->queueCmd(dbgCmd, expr,
1774 immediate ? DebuggerDriver::QMoverrideMoreEqual
1775 : DebuggerDriver::QMnormal);
1777 // remember which expression this was
1778 cmd->m_expr = var;
1779 cmd->m_exprWnd = wnd;
1782 void KDebugger::handleSharedLibs(const char* output)
1784 // delete all known libraries
1785 m_sharedLibs.clear();
1787 // parse the table of shared libraries
1788 m_d->parseSharedLibs(output, m_sharedLibs);
1789 m_sharedLibsListed = true;
1791 // get type libraries
1792 m_typeTable->loadLibTypes(m_sharedLibs);
1794 // hand over the QString data cmd
1795 m_d->setPrintQStringDataCmd(m_typeTable->printQStringDataCmd());
1798 CmdQueueItem* KDebugger::loadCoreFile()
1800 return m_d->queueCmd(DCcorefile, m_corefile, DebuggerDriver::QMoverride);
1803 void KDebugger::slotExpanding(QListViewItem* item)
1805 VarTree* exprItem = static_cast<VarTree*>(item);
1806 if (exprItem->m_varKind != VarTree::VKpointer) {
1807 return;
1809 ExprWnd* wnd = static_cast<ExprWnd*>(item->listView());
1810 dereferencePointer(wnd, exprItem, true);
1813 // add the expression in the edit field to the watch expressions
1814 void KDebugger::addWatch(const QString& t)
1816 QString expr = t.stripWhiteSpace();
1817 // don't add a watched expression again
1818 if (expr.isEmpty() || m_watchVariables.topLevelExprByName(expr) != 0)
1819 return;
1820 ExprValue e(expr, VarTree::NKplain);
1821 m_watchVariables.insertExpr(&e, *m_typeTable);
1823 // if we are boring ourselves, send down the command
1824 if (m_programActive) {
1825 m_watchEvalExpr.push_back(expr);
1826 if (m_d->isIdle()) {
1827 evalExpressions();
1832 // delete a toplevel watch expression
1833 void KDebugger::slotDeleteWatch()
1835 // delete only allowed while debugger is idle; or else we might delete
1836 // the very expression the debugger is currently working on...
1837 if (m_d == 0 || !m_d->isIdle())
1838 return;
1840 VarTree* item = m_watchVariables.currentItem();
1841 if (item == 0 || !item->isToplevelExpr())
1842 return;
1844 // remove the variable from the list to evaluate
1845 QStringList::iterator i = m_watchEvalExpr.find(item->getText());
1846 if (i != m_watchEvalExpr.end()) {
1847 m_watchEvalExpr.erase(i);
1849 m_watchVariables.removeExpr(item);
1850 // item is invalid at this point!
1853 void KDebugger::handleRegisters(const char* output)
1855 QList<RegisterInfo> regs;
1856 m_d->parseRegisters(output, regs);
1858 emit registersChanged(regs);
1860 // delete them all
1861 regs.setAutoDelete(true);
1865 * The output of the DCbreak* commands has more accurate information about
1866 * the file and the line number.
1868 * All newly set breakpoints are inserted in the m_brkpts, even those that
1869 * were not set sucessfully. The unsuccessful breakpoints ("orphaned
1870 * breakpoints") are assigned negative ids, and they are tried to set later
1871 * when the program stops again at a breakpoint.
1873 void KDebugger::newBreakpoint(CmdQueueItem* cmd, const char* output)
1875 Breakpoint* bp = cmd->m_brkpt;
1876 assert(bp != 0);
1877 if (bp == 0)
1878 return;
1880 // if this is a new breakpoint, put it in the list
1881 bool isNew = !m_brkpts.contains(bp);
1882 if (isNew) {
1883 assert(bp->id == 0);
1884 int n = m_brkpts.size();
1885 m_brkpts.resize(n+1);
1886 m_brkpts.insert(n, bp);
1889 // parse the output to determine success or failure
1890 int id;
1891 QString file;
1892 int lineNo;
1893 QString address;
1894 if (!m_d->parseBreakpoint(output, id, file, lineNo, address))
1897 * Failure, the breakpoint could not be set. If this is a new
1898 * breakpoint, assign it a negative id. We look for the minimal id
1899 * of all breakpoints (that are already in the list) to get the new
1900 * id.
1902 if (isNew)
1904 assert(bp->id == 0);
1905 for (int i = m_brkpts.size()-2; i >= 0; i--) {
1906 if (m_brkpts[i]->id < bp->id) {
1907 bp->id = m_brkpts[i]->id;
1908 break;
1911 --bp->id;
1913 return;
1916 // The breakpoint was successfully set.
1917 if (bp->id <= 0)
1919 // this is a new or orphaned breakpoint:
1920 // set the remaining properties
1921 if (!cmd->m_brkpt->enabled) {
1922 m_d->executeCmd(DCdisable, id);
1924 if (!cmd->m_brkpt->condition.isEmpty()) {
1925 m_d->executeCmd(DCcondition, cmd->m_brkpt->condition, id);
1929 bp->id = id;
1930 bp->fileName = file;
1931 bp->lineNo = lineNo;
1932 if (!address.isEmpty())
1933 bp->address = address;
1936 void KDebugger::updateBreakList(const char* output)
1938 // get the new list
1939 QList<Breakpoint> brks;
1940 brks.setAutoDelete(false);
1941 m_d->parseBreakList(output, brks);
1943 // merge new information into existing breakpoints
1945 for (int i = m_brkpts.size()-1; i >= 0; i--) // decrement!
1947 // skip orphaned breakpoints
1948 if (m_brkpts[i]->id < 0)
1949 continue;
1951 for (Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
1953 if (bp->id == m_brkpts[i]->id) {
1954 // keep accurate location
1955 // except that xsldbg doesn't have a location in
1956 // the old breakpoint if it's just been set
1957 bp->text = m_brkpts[i]->text;
1958 if (!m_brkpts[i]->fileName.isEmpty()) {
1959 bp->fileName = m_brkpts[i]->fileName;
1960 bp->lineNo = m_brkpts[i]->lineNo;
1962 m_brkpts.insert(i, bp); // old object is deleted
1963 goto stillAlive;
1967 * If we get here, this breakpoint is no longer present.
1969 * To delete the breakpoint at i, we place the last breakpoint in
1970 * the list into the slot i. This will delete the old object at i.
1971 * Then we shorten the list by one.
1973 m_brkpts.insert(i, m_brkpts.take(m_brkpts.size()-1));
1974 m_brkpts.resize(m_brkpts.size()-1);
1975 TRACE(QString().sprintf("deleted brkpt %d, have now %d brkpts", i, m_brkpts.size()));
1977 stillAlive:;
1980 // brks may contain new breakpoints not already in m_brkpts
1981 for (const Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
1983 bool found = false;
1984 for (uint i = 0; i < m_brkpts.size(); i++) {
1985 if (bp->id == m_brkpts[i]->id) {
1986 found = true;
1987 break;
1990 if (!found){
1991 int n = m_brkpts.size();
1992 m_brkpts.resize(n+1);
1993 m_brkpts.insert(n, bp);
1997 emit breakpointsChanged();
2000 // look if there is at least one temporary breakpoint
2001 // or a watchpoint
2002 bool KDebugger::stopMayChangeBreakList() const
2004 for (int i = m_brkpts.size()-1; i >= 0; i--) {
2005 Breakpoint* bp = m_brkpts[i];
2006 if (bp->temporary || bp->type == Breakpoint::watchpoint)
2007 return true;
2009 return false;
2012 Breakpoint* KDebugger::breakpointByFilePos(QString file, int lineNo,
2013 const DbgAddr& address)
2015 // look for exact file name match
2016 int i;
2017 for (i = m_brkpts.size()-1; i >= 0; i--) {
2018 if (m_brkpts[i]->lineNo == lineNo &&
2019 m_brkpts[i]->fileName == file &&
2020 (address.isEmpty() || m_brkpts[i]->address == address))
2022 return m_brkpts[i];
2025 // not found, so try basename
2026 // strip off directory part of file name
2027 int offset = file.findRev("/");
2028 file.remove(0, offset+1);
2030 for (i = m_brkpts.size()-1; i >= 0; i--) {
2031 // get base name of breakpoint's file
2032 QString basename = m_brkpts[i]->fileName;
2033 int offset = basename.findRev("/");
2034 if (offset >= 0) {
2035 basename.remove(0, offset+1);
2038 if (m_brkpts[i]->lineNo == lineNo &&
2039 basename == file &&
2040 (address.isEmpty() || m_brkpts[i]->address == address))
2042 return m_brkpts[i];
2046 // not found
2047 return 0;
2050 Breakpoint* KDebugger::breakpointById(int id)
2052 for (int i = m_brkpts.size()-1; i >= 0; i--)
2054 if (m_brkpts[i]->id == id) {
2055 return m_brkpts[i];
2058 // not found
2059 return 0;
2062 void KDebugger::slotValuePopup(const QString& expr)
2064 // search the local variables for a match
2065 VarTree* v = m_localVariables.topLevelExprByName(expr);
2066 if (v == 0) {
2067 // not found, check watch expressions
2068 v = m_watchVariables.topLevelExprByName(expr);
2069 if (v == 0) {
2070 // try a member of 'this'
2071 v = m_localVariables.topLevelExprByName("this");
2072 if (v != 0)
2073 v = ExprWnd::ptrMemberByName(v, expr);
2074 if (v == 0) {
2075 // nothing found; do nothing
2076 return;
2081 // construct the tip
2082 QString tip = v->getText() + " = ";
2083 if (!v->value().isEmpty())
2085 tip += v->value();
2087 else
2089 // no value: we use some hint
2090 switch (v->m_varKind) {
2091 case VarTree::VKstruct:
2092 tip += "{...}";
2093 break;
2094 case VarTree::VKarray:
2095 tip += "[...]";
2096 break;
2097 default:
2098 tip += "?""?""?"; // 2 question marks in a row would be a trigraph
2099 break;
2102 emit valuePopup(tip);
2105 void KDebugger::slotDisassemble(const QString& fileName, int lineNo)
2107 if (m_haveExecutable) {
2108 CmdQueueItem* cmd = m_d->queueCmd(DCinfoline, fileName, lineNo,
2109 DebuggerDriver::QMoverrideMoreEqual);
2110 cmd->m_fileName = fileName;
2111 cmd->m_lineNo = lineNo;
2115 void KDebugger::handleInfoLine(CmdQueueItem* cmd, const char* output)
2117 QString addrFrom, addrTo;
2118 if (cmd->m_lineNo >= 0) {
2119 // disassemble
2120 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2121 // got the address range, now get the real code
2122 CmdQueueItem* c = m_d->queueCmd(DCdisassemble, addrFrom, addrTo,
2123 DebuggerDriver::QMoverrideMoreEqual);
2124 c->m_fileName = cmd->m_fileName;
2125 c->m_lineNo = cmd->m_lineNo;
2126 } else {
2127 // no code
2128 QList<DisassembledCode> empty;
2129 emit disassembled(cmd->m_fileName, cmd->m_lineNo, empty);
2131 } else {
2132 // set program counter
2133 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
2134 // move the program counter to the start address
2135 m_d->executeCmd(DCsetpc, addrFrom);
2140 void KDebugger::handleDisassemble(CmdQueueItem* cmd, const char* output)
2142 QList<DisassembledCode> code;
2143 code.setAutoDelete(true);
2144 m_d->parseDisassemble(output, code);
2145 emit disassembled(cmd->m_fileName, cmd->m_lineNo, code);
2148 void KDebugger::handleThreadList(const char* output)
2150 QList<ThreadInfo> threads;
2151 threads.setAutoDelete(true);
2152 m_d->parseThreadList(output, threads);
2153 emit threadsChanged(threads);
2156 void KDebugger::setThread(int id)
2158 m_d->queueCmd(DCthread, id, DebuggerDriver::QMoverrideMoreEqual);
2161 void KDebugger::setMemoryExpression(const QString& memexpr)
2163 m_memoryExpression = memexpr;
2165 // queue the new expression
2166 if (!m_memoryExpression.isEmpty() &&
2167 isProgramActive() &&
2168 !isProgramRunning())
2170 queueMemoryDump(true);
2174 void KDebugger::queueMemoryDump(bool immediate)
2176 m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat,
2177 immediate ? DebuggerDriver::QMoverrideMoreEqual :
2178 DebuggerDriver::QMoverride);
2181 void KDebugger::handleMemoryDump(const char* output)
2183 QList<MemoryDump> memdump;
2184 memdump.setAutoDelete(true);
2185 QString msg = m_d->parseMemoryDump(output, memdump);
2186 emit memoryDumpChanged(msg, memdump);
2189 void KDebugger::setProgramCounter(const QString& file, int line, const DbgAddr& addr)
2191 if (addr.isEmpty()) {
2192 // find address of the specified line
2193 CmdQueueItem* cmd = m_d->executeCmd(DCinfoline, file, line);
2194 cmd->m_lineNo = -1; /* indicates "Set PC" UI command */
2195 } else {
2196 // move the program counter to that address
2197 m_d->executeCmd(DCsetpc, addr.asString());
2201 void KDebugger::handleSetPC(const char* /*output*/)
2203 // TODO: handle errors
2205 // now go to the top-most frame
2206 // this also modifies the program counter indicator in the UI
2207 gotoFrame(0);
2210 void KDebugger::slotValueEdited(VarTree* expr, const QString& text)
2212 if (text.simplifyWhiteSpace().isEmpty())
2213 return; /* no text entered: ignore request */
2215 ExprWnd* wnd = static_cast<ExprWnd*>(expr->listView());
2216 TRACE(QString().sprintf("Changing %s to ",
2217 wnd->name()) + text);
2219 // determine the lvalue to edit
2220 QString lvalue = expr->computeExpr();
2221 CmdQueueItem* cmd = m_d->executeCmd(DCsetvariable, lvalue, text);
2222 cmd->m_expr = expr;
2223 cmd->m_exprWnd = wnd;
2226 void KDebugger::handleSetVariable(CmdQueueItem* cmd, const char* output)
2228 QString msg = m_d->parseSetVariable(output);
2229 if (!msg.isEmpty())
2231 // there was an error; display it in the status bar
2232 m_statusMessage = msg;
2233 emit updateStatusMessage();
2234 return;
2237 // get the new value
2238 QString expr = cmd->m_expr->computeExpr();
2239 CmdQueueItem* printCmd =
2240 m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverrideMoreEqual);
2241 printCmd->m_expr = cmd->m_expr;
2242 printCmd->m_exprWnd = cmd->m_exprWnd;
2246 #include "debugger.moc"