When looking up breakpoints by file name, in the second phase where only
[kdbg.git] / kdbg / debugger.cpp
blob77b90f14ddef1a8c38f7864dcba7908dca79fbe2
1 // $Id$
3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include "debugger.h"
7 #include "dbgdriver.h"
8 #include "pgmargs.h"
9 #include "typetable.h"
10 #include "exprwnd.h"
11 #include "pgmsettings.h"
12 #include "valarray.h"
13 #include <qregexp.h>
14 #include <qfileinfo.h>
15 #include <qlistbox.h>
16 #include <kapp.h>
17 #include <ksimpleconfig.h>
18 #include <kconfig.h>
19 #if QT_VERSION >= 200
20 #include <klocale.h> /* i18n */
21 #include <kmessagebox.h>
22 #else
23 #include <kmsgbox.h>
24 #endif
25 #include <ctype.h>
26 #include <stdlib.h> /* strtol, atoi */
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h> /* sleep(3) */
29 #endif
30 #include "mydebug.h"
33 KDebugger::KDebugger(QWidget* parent,
34 ExprWnd* localVars,
35 ExprWnd* watchVars,
36 QListBox* backtrace,
37 DebuggerDriver* driver
38 ) :
39 QObject(parent, "debugger"),
40 m_ttyLevel(ttyFull),
41 m_memoryFormat(MDTword | MDThex),
42 m_haveExecutable(false),
43 m_programActive(false),
44 m_programRunning(false),
45 m_sharedLibsListed(false),
46 m_typeTable(0),
47 m_programConfig(0),
48 m_d(driver),
49 m_localVariables(*localVars),
50 m_watchVariables(*watchVars),
51 m_btWindow(*backtrace),
52 m_animationTimer(this),
53 m_animationInterval(0)
55 m_envVars.setAutoDelete(true);
57 connect(&m_localVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
58 SLOT(slotLocalsExpanding(KTreeViewItem*,bool&)));
59 connect(&m_watchVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
60 SLOT(slotWatchExpanding(KTreeViewItem*,bool&)));
62 connect(&m_btWindow, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
64 connect(m_d, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
65 this, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)));
67 // debugger process
68 connect(m_d, SIGNAL(processExited(KProcess*)), SLOT(gdbExited(KProcess*)));
69 connect(m_d, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
70 SLOT(parse(CmdQueueItem*,const char*)));
71 connect(m_d, SIGNAL(wroteStdin(KProcess*)), SIGNAL(updateUI()));
72 connect(m_d, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
73 connect(m_d, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
74 connect(m_d, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
76 // animation
77 connect(&m_animationTimer, SIGNAL(timeout()), SIGNAL(animationTimeout()));
78 // special update of animation
79 connect(this, SIGNAL(updateUI()), SLOT(slotUpdateAnimation()));
81 emit updateUI();
84 KDebugger::~KDebugger()
86 if (m_programConfig != 0) {
87 saveProgramSettings();
88 m_programConfig->sync();
89 delete m_programConfig;
91 // delete breakpoint objects
92 for (int i = m_brkpts.size()-1; i >= 0; i--) {
93 delete m_brkpts[i];
96 delete m_typeTable;
100 void KDebugger::saveSettings(KConfig* /*config*/)
104 void KDebugger::restoreSettings(KConfig* /*config*/)
109 //////////////////////////////////////////////////////////////////////
110 // external interface
112 const char GeneralGroup[] = "General";
113 const char DebuggerCmdStr[] = "DebuggerCmdStr";
114 const char TTYLevelEntry[] = "TTYLevel";
116 bool KDebugger::debugProgram(const QString& name)
118 if (m_d->isRunning())
120 QApplication::setOverrideCursor(waitCursor);
122 stopDriver();
124 QApplication::restoreOverrideCursor();
126 if (m_d->isRunning() || m_haveExecutable) {
127 /* timed out! We can't really do anything useful now */
128 TRACE("timed out while waiting for gdb to die!");
129 return false;
133 // create the program settings object
134 openProgramConfig(name);
136 // get debugger command from per-program settings
137 if (m_programConfig != 0) {
138 m_programConfig->setGroup(GeneralGroup);
139 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
140 // get terminal emulation level
141 m_ttyLevel = TTYLevel(m_programConfig->readNumEntry(TTYLevelEntry, ttyFull));
143 // the rest is read in later in the handler of DCexecutable
145 if (!startDriver()) {
146 TRACE("startDriver failed");
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->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::programRun()
192 if (!isReady())
193 return;
195 // when program is active, but not a core file, continue
196 // otherwise run the program
197 if (m_programActive && m_corefile.isEmpty()) {
198 // gdb command: continue
199 m_d->executeCmd(DCcont, true);
200 } else {
201 // gdb command: run
202 m_d->executeCmd(DCrun, true);
203 m_corefile = QString();
204 m_programActive = true;
206 m_programRunning = true;
209 void KDebugger::attachProgram(const QString& pid)
211 if (!isReady())
212 return;
214 m_attachedPid = pid;
215 TRACE("Attaching to " + m_attachedPid);
216 m_d->executeCmd(DCattach, m_attachedPid);
217 m_programActive = true;
218 m_programRunning = true;
221 void KDebugger::programRunAgain()
223 if (canSingleStep()) {
224 m_d->executeCmd(DCrun, true);
225 m_corefile = QString();
226 m_programRunning = true;
230 void KDebugger::programStep(bool byInsn)
232 if (canSingleStep()) {
233 m_d->executeCmd(byInsn ? DCstepi : DCstep, true);
234 m_programRunning = true;
238 void KDebugger::programNext(bool byInsn)
240 if (canSingleStep()) {
241 m_d->executeCmd(byInsn ? DCnexti : DCnext, true);
242 m_programRunning = true;
246 void KDebugger::programFinish()
248 if (canSingleStep()) {
249 m_d->executeCmd(DCfinish, true);
250 m_programRunning = true;
254 void KDebugger::programKill()
256 if (haveExecutable() && isProgramActive()) {
257 if (m_programRunning) {
258 m_d->interruptInferior();
260 // this is an emergency command; flush queues
261 m_d->flushCommands(true);
262 m_d->executeCmd(DCkill, true);
266 bool KDebugger::runUntil(const QString& fileName, int lineNo)
268 if (isReady() && m_programActive && !m_programRunning) {
269 // strip off directory part of file name
270 QString file = fileName;
271 #if QT_VERSION < 200
272 file.detach();
273 #endif
274 int offset = file.findRev("/");
275 if (offset >= 0) {
276 file.remove(0, offset+1);
278 m_d->executeCmd(DCuntil, file, lineNo, true);
279 m_programRunning = true;
280 return true;
281 } else {
282 return false;
286 void KDebugger::programBreak()
288 if (m_haveExecutable && m_programRunning) {
289 m_d->interruptInferior();
293 void KDebugger::programArgs(QWidget* parent)
295 if (m_haveExecutable) {
296 PgmArgs dlg(parent, m_executable, m_envVars);
297 dlg.setArgs(m_programArgs);
298 dlg.setWd(m_programWD);
299 if (dlg.exec()) {
300 updateProgEnvironment(dlg.args(), dlg.wd(), dlg.envVars());
305 void KDebugger::programSettings(QWidget* parent)
307 if (!m_haveExecutable)
308 return;
310 ProgramSettings dlg(parent, m_executable);
312 dlg.m_chooseDriver.setDebuggerCmd(m_debuggerCmd);
313 dlg.m_output.setTTYLevel(m_ttyLevel);
315 if (dlg.exec() == QDialog::Accepted)
317 m_debuggerCmd = dlg.m_chooseDriver.debuggerCmd();
318 m_ttyLevel = TTYLevel(dlg.m_output.ttyLevel());
322 bool KDebugger::setBreakpoint(QString file, int lineNo,
323 const DbgAddr& address, bool temporary)
325 if (!isReady()) {
326 return false;
329 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
330 if (bp == 0)
333 * No such breakpoint, so set a new one. If we have an address, we
334 * set the breakpoint exactly there. Otherwise we use the file name
335 * plus line no.
337 if (address.isEmpty())
339 // strip off directory part of file name
340 #if QT_VERSION < 200
341 file.detach();
342 #endif
343 int offset = file.findRev("/");
344 if (offset >= 0) {
345 file.remove(0, offset+1);
347 m_d->executeCmd(temporary ? DCtbreakline : DCbreakline,
348 file, lineNo);
350 else
352 m_d->executeCmd(temporary ? DCtbreakaddr : DCbreakaddr,
353 address.asString());
356 else
359 * If the breakpoint is disabled, enable it; if it's enabled,
360 * delete that breakpoint.
362 if (bp->enabled) {
363 m_d->executeCmd(DCdelete, bp->id);
364 } else {
365 m_d->executeCmd(DCenable, bp->id);
368 return true;
371 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo,
372 const DbgAddr& address)
374 if (!isReady()) {
375 return false;
378 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
379 if (bp == 0)
380 return true;
382 // toggle enabled/disabled state
383 if (bp->enabled) {
384 m_d->executeCmd(DCdisable, bp->id);
385 } else {
386 m_d->executeCmd(DCenable, bp->id);
388 return true;
391 bool KDebugger::canSingleStep()
393 return isReady() && m_programActive && !m_programRunning;
396 bool KDebugger::canChangeBreakpoints()
398 return isReady() && !m_programRunning;
401 bool KDebugger::isReady() const
403 return m_haveExecutable &&
404 m_d->canExecuteImmediately();
407 bool KDebugger::isIdle() const
409 return m_d->isIdle();
413 //////////////////////////////////////////////////////////
414 // debugger driver
416 bool KDebugger::startDriver()
418 emit debuggerStarting(); /* must set m_inferiorTerminal */
421 * If the per-program command string is empty, use the global setting
422 * (which might also be empty, in which case the driver uses its
423 * default).
425 QString debuggerCmd = m_debuggerCmd.isEmpty() ?
426 m_generalDebuggerCmd : m_debuggerCmd;
427 m_explicitKill = false;
428 if (!m_d->startup(debuggerCmd)) {
429 return false;
433 * If we have an output terminal, we use it. Otherwise we will run the
434 * program with input and output redirected to /dev/null. Other
435 * redirections are also necessary depending on the tty emulation
436 * level.
438 int redirect = RDNstdin|RDNstdout|RDNstderr; /* redirect everything */
439 if (!m_inferiorTerminal.isEmpty()) {
440 switch (m_ttyLevel) {
441 default:
442 case ttyNone:
443 // redirect everything
444 break;
445 case ttySimpleOutputOnly:
446 redirect = RDNstdin;
447 break;
448 case ttyFull:
449 redirect = 0;
450 break;
453 m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
455 return true;
458 void KDebugger::stopDriver()
460 m_explicitKill = true;
462 if (m_attachedPid.isEmpty()) {
463 m_d->terminate();
464 } else {
465 m_d->detachAndTerminate();
469 * We MUST wait until the slot gdbExited() has been called. But to
470 * avoid a deadlock, we wait only for some certain maximum time. Should
471 * this timeout be reached, the only reasonable thing one could do then
472 * is exiting kdbg.
474 kapp->processEvents(1000); /* ideally, this will already shut it down */
475 int maxTime = 20; /* about 20 seconds */
476 while (m_haveExecutable && maxTime > 0) {
477 // give gdb time to die (and send a SIGCLD)
478 ::sleep(1);
479 --maxTime;
480 kapp->processEvents(1000);
484 void KDebugger::gdbExited(KProcess*)
487 * Save settings, but only if gdb has already processed "info line
488 * main", otherwise we would save an empty config file, because it
489 * isn't read in until then!
491 if (m_programConfig != 0) {
492 if (m_haveExecutable) {
493 saveProgramSettings();
494 m_programConfig->sync();
496 delete m_programConfig;
497 m_programConfig = 0;
500 // erase types
501 delete m_typeTable;
502 m_typeTable = 0;
504 if (m_explicitKill) {
505 TRACE("gdb exited normally");
506 } else {
507 QString msg = i18n("gdb exited unexpectedly.\n"
508 "Restart the session (e.g. with File|Executable).");
509 #if QT_VERSION < 200
510 KMsgBox::message(parentWidget(), kapp->appName(), msg, KMsgBox::EXCLAMATION);
511 #else
512 KMessageBox::error(parentWidget(), msg);
513 #endif
516 // reset state
517 m_haveExecutable = false;
518 m_executable = "";
519 m_programActive = false;
520 m_programRunning = false;
521 m_explicitKill = false;
522 m_debuggerCmd = QString(); /* use global setting at next start! */
523 m_attachedPid = QString(); /* we are no longer attached to a process */
524 m_ttyLevel = ttyFull;
526 // stop gear wheel and erase PC
527 stopAnimation();
528 emit updatePC(QString(), -1, DbgAddr(), 0);
531 void KDebugger::openProgramConfig(const QString& name)
533 ASSERT(m_programConfig == 0);
535 QFileInfo fi(name);
536 QString pgmConfigFile = fi.dirPath(true);
537 if (!pgmConfigFile.isEmpty()) {
538 pgmConfigFile += '/';
540 pgmConfigFile += ".kdbgrc." + fi.fileName();
541 TRACE("program config file = " + pgmConfigFile);
542 // check whether we can write to the file
543 QFile file(pgmConfigFile);
544 bool readonly = true;
545 bool openit = true;
546 if (file.open(IO_ReadWrite)) { /* don't truncate! */
547 readonly = false;
548 // the file exists now
549 } else if (!file.open(IO_ReadOnly)) {
550 /* file does not exist and cannot be created: don't use it */
551 openit = false;
553 if (openit) {
554 m_programConfig = new KSimpleConfig(pgmConfigFile, readonly);
558 const char EnvironmentGroup[] = "Environment";
559 const char WatchGroup[] = "Watches";
560 const char FileVersion[] = "FileVersion";
561 const char ProgramArgs[] = "ProgramArgs";
562 const char WorkingDirectory[] = "WorkingDirectory";
563 const char Variable[] = "Var%d";
564 const char Value[] = "Value%d";
565 const char ExprFmt[] = "Expr%d";
567 void KDebugger::saveProgramSettings()
569 ASSERT(m_programConfig != 0);
570 m_programConfig->setGroup(GeneralGroup);
571 m_programConfig->writeEntry(FileVersion, 1);
572 m_programConfig->writeEntry(ProgramArgs, m_programArgs);
573 m_programConfig->writeEntry(WorkingDirectory, m_programWD);
574 m_programConfig->writeEntry(DebuggerCmdStr, m_debuggerCmd);
575 m_programConfig->writeEntry(TTYLevelEntry, int(m_ttyLevel));
577 // write environment variables
578 m_programConfig->deleteGroup(EnvironmentGroup);
579 m_programConfig->setGroup(EnvironmentGroup);
580 QDictIterator<EnvVar> it = m_envVars;
581 EnvVar* var;
582 QString varName;
583 QString varValue;
584 for (int i = 0; (var = it) != 0; ++it, ++i) {
585 varName.sprintf(Variable, i);
586 varValue.sprintf(Value, i);
587 m_programConfig->writeEntry(varName, it.currentKey());
588 m_programConfig->writeEntry(varValue, var->value);
591 saveBreakpoints(m_programConfig);
593 // watch expressions
594 // first get rid of whatever was in this group
595 m_programConfig->deleteGroup(WatchGroup);
596 // then start a new group
597 m_programConfig->setGroup(WatchGroup);
598 KTreeViewItem* item = m_watchVariables.itemAt(0);
599 int watchNum = 0;
600 for (; item != 0; item = item->getSibling(), ++watchNum) {
601 varName.sprintf(ExprFmt, watchNum);
602 m_programConfig->writeEntry(varName, item->getText());
605 // give others a chance
606 emit saveProgramSpecific(m_programConfig);
609 void KDebugger::restoreProgramSettings()
611 ASSERT(m_programConfig != 0);
612 m_programConfig->setGroup(GeneralGroup);
614 * We ignore file version for now we will use it in the future to
615 * distinguish different versions of this configuration file.
617 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
618 // m_ttyLevel has been read in already
619 QString pgmArgs = m_programConfig->readEntry(ProgramArgs);
620 QString pgmWd = m_programConfig->readEntry(WorkingDirectory);
622 // read environment variables
623 m_programConfig->setGroup(EnvironmentGroup);
624 m_envVars.clear();
625 QDict<EnvVar> pgmVars;
626 EnvVar* var;
627 QString varName;
628 QString varValue;
629 for (int i = 0;; ++i) {
630 varName.sprintf(Variable, i);
631 varValue.sprintf(Value, i);
632 if (!m_programConfig->hasKey(varName)) {
633 /* entry not present, assume that we've hit them all */
634 break;
636 QString name = m_programConfig->readEntry(varName);
637 if (name.isEmpty()) {
638 // skip empty names
639 continue;
641 var = new EnvVar;
642 var->value = m_programConfig->readEntry(varValue);
643 var->status = EnvVar::EVnew;
644 pgmVars.insert(name, var);
647 updateProgEnvironment(pgmArgs, pgmWd, pgmVars);
649 restoreBreakpoints(m_programConfig);
651 // watch expressions
652 m_programConfig->setGroup(WatchGroup);
653 m_watchVariables.clear();
654 for (int i = 0;; ++i) {
655 varName.sprintf(ExprFmt, i);
656 if (!m_programConfig->hasKey(varName)) {
657 /* entry not present, assume that we've hit them all */
658 break;
660 QString expr = m_programConfig->readEntry(varName);
661 if (expr.isEmpty()) {
662 // skip empty expressions
663 continue;
665 addWatch(expr);
668 // give others a chance
669 emit restoreProgramSpecific(m_programConfig);
673 * Breakpoints are saved one per group.
675 const char BPGroup[] = "Breakpoint %d";
676 const char File[] = "File";
677 const char Line[] = "Line";
678 const char Address[] = "Address";
679 const char Temporary[] = "Temporary";
680 const char Enabled[] = "Enabled";
681 const char Condition[] = "Condition";
683 void KDebugger::saveBreakpoints(KSimpleConfig* config)
685 QString groupName;
686 int i = 0;
687 for (uint j = 0; j < m_brkpts.size(); j++) {
688 Breakpoint* bp = m_brkpts[j];
689 if (bp->type == Breakpoint::watchpoint)
690 continue; /* don't save watchpoints */
691 groupName.sprintf(BPGroup, i++);
692 config->setGroup(groupName);
693 if (!bp->fileName.isEmpty()) {
694 config->writeEntry(File, bp->fileName);
695 config->writeEntry(Line, bp->lineNo);
697 * Addresses are hardly correct across sessions, so we remove
698 * it since we have a file name and line number.
700 config->deleteEntry(Address, false);
701 } else {
702 config->writeEntry(Address, bp->address.asString());
703 /* remove remmants */
704 config->deleteEntry(File, false);
705 config->deleteEntry(Line, false);
707 config->writeEntry(Temporary, bp->temporary);
708 config->writeEntry(Enabled, bp->enabled);
709 if (bp->condition.isEmpty())
710 config->deleteEntry(Condition, false);
711 else
712 config->writeEntry(Condition, bp->condition);
713 // we do not save the ignore count
715 // delete remaining groups
716 // we recognize that a group is present if there is an Enabled entry
717 for (;; i++) {
718 groupName.sprintf(BPGroup, i);
719 config->setGroup(groupName);
720 if (!config->hasKey(Enabled)) {
721 /* group not present, assume that we've hit them all */
722 break;
724 config->deleteGroup(groupName);
728 void KDebugger::restoreBreakpoints(KSimpleConfig* config)
730 QString groupName;
731 QString fileName;
732 QString address;
733 int lineNo;
734 bool enabled, temporary;
735 QString condition;
737 * We recognize the end of the list if there is no Enabled entry
738 * present.
740 for (int i = 0;; i++) {
741 groupName.sprintf(BPGroup, i);
742 config->setGroup(groupName);
743 if (!config->hasKey(Enabled)) {
744 /* group not present, assume that we've hit them all */
745 break;
747 fileName = config->readEntry(File);
748 lineNo = config->readNumEntry(Line, -1);
749 address = config->readEntry(Address);
750 if ((fileName.isEmpty() || lineNo < 0) && address.isEmpty())
751 continue;
752 enabled = config->readBoolEntry(Enabled, true);
753 temporary = config->readBoolEntry(Temporary, false);
754 condition = config->readEntry(Condition);
756 * Add the breakpoint. We assume that we have started a new
757 * instance of gdb, because we assign the breakpoint ids ourselves,
758 * starting with 1. Then we use this id to disable the breakpoint,
759 * if necessary. If this assignment of ids doesn't work, (maybe
760 * because this isn't a fresh gdb at all), we disable the wrong
761 * breakpoint! Oh well... for now it works.
763 if (!fileName.isEmpty()) {
764 m_d->executeCmd(temporary ? DCtbreakline : DCbreakline,
765 fileName, lineNo);
766 } else {
767 m_d->executeCmd(temporary ? DCtbreakaddr : DCbreakaddr,
768 address);
770 if (!enabled) {
771 m_d->executeCmd(DCdisable, i+1);
773 if (!condition.isEmpty()) {
774 m_d->executeCmd(DCcondition, condition, i+1);
777 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
781 // parse output of command cmd
782 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
784 ASSERT(cmd != 0); /* queue mustn't be empty */
786 TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
788 switch (cmd->m_cmd) {
789 case DCtargetremote:
790 // the output (if any) is uninteresting
791 case DCsetargs:
792 case DCtty:
793 // there is no output
794 case DCsetenv:
795 case DCunsetenv:
796 /* if value is empty, we see output, but we don't care */
797 break;
798 case DCcd:
799 /* display gdb's message in the status bar */
800 m_d->parseChangeWD(output, m_statusMessage);
801 emit updateStatusMessage();
802 break;
803 case DCinitialize:
804 break;
805 case DCexecutable:
806 if (m_d->parseChangeExecutable(output, m_statusMessage))
808 // success; restore breakpoints etc.
809 if (m_programConfig != 0) {
810 restoreProgramSettings();
812 // load file containing main() or core file
813 if (m_corefile.isEmpty()) {
814 if (m_remoteDevice.isEmpty())
815 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
816 } else {
817 // load core file
818 loadCoreFile();
820 if (!m_statusMessage.isEmpty())
821 emit updateStatusMessage();
822 } else {
823 QString msg = "gdb: " + m_statusMessage;
824 #if QT_VERSION < 200
825 KMsgBox::message(parentWidget(), kapp->appName(), msg,
826 KMsgBox::STOP, i18n("OK"));
827 #else
828 KMessageBox::sorry(parentWidget(), msg);
829 #endif
830 m_executable = "";
831 m_corefile = ""; /* don't process core file */
832 m_haveExecutable = false;
834 break;
835 case DCcorefile:
836 // in any event we have an executable at this point
837 m_haveExecutable = true;
838 if (m_d->parseCoreFile(output)) {
839 // loading a core is like stopping at a breakpoint
840 m_programActive = true;
841 handleRunCommands(output);
842 // do not reset m_corefile
843 } else {
844 // report error
845 QString msg = m_d->driverName() + ": " + QString(output);
846 #if QT_VERSION < 200
847 KMsgBox::message(parentWidget(), kapp->appName(), msg,
848 KMsgBox::EXCLAMATION, i18n("OK"));
849 #else
850 KMessageBox::sorry(parentWidget(), msg);
851 #endif
852 // if core file was loaded from command line, revert to info line main
853 if (!cmd->m_byUser) {
854 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
856 m_corefile = QString(); /* core file not available any more */
858 break;
859 case DCinfolinemain:
860 // ignore the output, marked file info follows
861 m_haveExecutable = true;
862 break;
863 case DCinfolocals:
864 // parse local variables
865 if (output[0] != '\0') {
866 handleLocals(output);
868 break;
869 case DCinforegisters:
870 handleRegisters(output);
871 break;
872 case DCexamine:
873 handleMemoryDump(output);
874 break;
875 case DCinfoline:
876 handleInfoLine(cmd, output);
877 break;
878 case DCdisassemble:
879 handleDisassemble(cmd, output);
880 break;
881 case DCframe:
882 handleFrameChange(output);
883 updateAllExprs();
884 break;
885 case DCbt:
886 handleBacktrace(output);
887 updateAllExprs();
888 break;
889 case DCprint:
890 handlePrint(cmd, output);
891 break;
892 case DCattach:
893 case DCrun:
894 case DCcont:
895 case DCstep:
896 case DCstepi:
897 case DCnext:
898 case DCnexti:
899 case DCfinish:
900 case DCuntil:
901 case DCthread:
902 handleRunCommands(output);
903 break;
904 case DCkill:
905 m_programRunning = m_programActive = false;
906 // erase PC
907 emit updatePC(QString(), -1, DbgAddr(), 0);
908 break;
909 case DCbreaktext:
910 case DCbreakline:
911 case DCtbreakline:
912 case DCbreakaddr:
913 case DCtbreakaddr:
914 case DCwatchpoint:
915 newBreakpoint(output);
916 // fall through
917 case DCdelete:
918 case DCenable:
919 case DCdisable:
920 // these commands need immediate response
921 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverrideMoreEqual);
922 break;
923 case DCinfobreak:
924 // note: this handler must not enqueue a command, since
925 // DCinfobreak is used at various different places.
926 updateBreakList(output);
927 emit lineItemsChanged();
928 break;
929 case DCfindType:
930 handleFindType(cmd, output);
931 break;
932 case DCprintStruct:
933 case DCprintQStringStruct:
934 handlePrintStruct(cmd, output);
935 break;
936 case DCinfosharedlib:
937 handleSharedLibs(output);
938 break;
939 case DCcondition:
940 case DCignore:
941 // we are not interested in the output
942 break;
943 case DCinfothreads:
944 handleThreadList(output);
945 break;
949 void KDebugger::backgroundUpdate()
952 * If there are still expressions that need to be updated, then do so.
954 if (m_programActive)
955 evalExpressions();
958 void KDebugger::handleRunCommands(const char* output)
960 uint flags = m_d->parseProgramStopped(output, m_statusMessage);
961 emit updateStatusMessage();
963 m_programActive = flags & DebuggerDriver::SFprogramActive;
965 // refresh files if necessary
966 if (flags & DebuggerDriver::SFrefreshSource) {
967 TRACE("re-reading files");
968 emit executableUpdated();
972 * If we stopped at a breakpoint, we must update the breakpoint list
973 * because the hit count changes. Also, if the breakpoint was temporary
974 * it would go away now.
976 if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
977 stopMayChangeBreakList())
979 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
983 * If we haven't listed the shared libraries yet, do so. We must do
984 * this before we emit any commands that list variables, since the type
985 * libraries depend on the shared libraries.
987 if (!m_sharedLibsListed) {
988 // must be a high-priority command!
989 m_d->executeCmd(DCinfosharedlib);
992 // get the backtrace if the program is running
993 if (m_programActive) {
994 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
995 } else {
996 // program finished: erase PC
997 emit updatePC(QString(), -1, DbgAddr(), 0);
998 // dequeue any commands in the queues
999 m_d->flushCommands();
1002 /* Update threads list */
1003 if (flags & DebuggerDriver::SFrefreshThreads) {
1004 m_d->queueCmd(DCinfothreads, DebuggerDriver::QMoverride);
1007 m_programRunning = false;
1008 emit programStopped();
1011 void KDebugger::slotInferiorRunning()
1013 m_programRunning = true;
1016 void KDebugger::updateAllExprs()
1018 if (!m_programActive)
1019 return;
1021 // retrieve local variables
1022 m_d->queueCmd(DCinfolocals, DebuggerDriver::QMoverride);
1024 // retrieve registers
1025 m_d->queueCmd(DCinforegisters, DebuggerDriver::QMoverride);
1027 // get new memory dump
1028 if (!m_memoryExpression.isEmpty()) {
1029 queueMemoryDump(false);
1032 // update watch expressions
1033 KTreeViewItem* item = m_watchVariables.itemAt(0);
1034 for (; item != 0; item = item->getSibling()) {
1035 m_watchEvalExpr.append(static_cast<VarTree*>(item));
1039 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
1040 const QDict<EnvVar>& newVars)
1042 m_programArgs = args;
1043 m_d->executeCmd(DCsetargs, m_programArgs);
1044 TRACE("new pgm args: " + m_programArgs + "\n");
1046 m_programWD = wd.stripWhiteSpace();
1047 if (!m_programWD.isEmpty()) {
1048 m_d->executeCmd(DCcd, m_programWD);
1049 TRACE("new wd: " + m_programWD + "\n");
1052 QDictIterator<EnvVar> it = newVars;
1053 EnvVar* val;
1054 for (; (val = it) != 0; ++it) {
1055 QString var = it.currentKey();
1056 switch (val->status) {
1057 case EnvVar::EVnew:
1058 m_envVars.insert(var, val);
1059 // fall thru
1060 case EnvVar::EVdirty:
1061 // the value must be in our list
1062 ASSERT(m_envVars[var] == val);
1063 // update value
1064 m_d->executeCmd(DCsetenv, var, val->value);
1065 break;
1066 case EnvVar::EVdeleted:
1067 // must be in our list
1068 ASSERT(m_envVars[var] == val);
1069 // delete value
1070 m_d->executeCmd(DCunsetenv, var);
1071 m_envVars.remove(var);
1072 break;
1073 default:
1074 ASSERT(false);
1075 case EnvVar::EVclean:
1076 // variable not changed
1077 break;
1082 void KDebugger::handleLocals(const char* output)
1084 // retrieve old list of local variables
1085 QStrList oldVars;
1086 m_localVariables.exprList(oldVars);
1089 * Get local variables.
1091 QList<VarTree> newVars;
1092 parseLocals(output, newVars);
1095 * Clear any old VarTree item pointers, so that later we don't access
1096 * dangling pointers.
1098 m_localVariables.clearPendingUpdates();
1100 // reduce flicker
1101 bool autoU = m_localVariables.autoUpdate();
1102 m_localVariables.setAutoUpdate(false);
1103 bool repaintNeeded = false;
1106 * Match old variables against new ones.
1108 for (const char* n = oldVars.first(); n != 0; n = oldVars.next()) {
1109 // lookup this variable in the list of new variables
1110 VarTree* v = newVars.first();
1111 while (v != 0 && strcmp(v->getText(), n) != 0) {
1112 v = newVars.next();
1114 if (v == 0) {
1115 // old variable not in the new variables
1116 TRACE(QString("old var deleted: ") + n);
1117 v = m_localVariables.topLevelExprByName(n);
1118 removeExpr(&m_localVariables, v);
1119 if (v != 0) repaintNeeded = true;
1120 } else {
1121 // variable in both old and new lists: update
1122 TRACE(QString("update var: ") + n);
1123 m_localVariables.updateExpr(newVars.current());
1124 // remove the new variable from the list
1125 newVars.remove();
1126 delete v;
1127 #if QT_VERSION >= 200
1128 repaintNeeded = true;
1129 #endif
1132 // insert all remaining new variables
1133 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1134 TRACE("new var: " + v->getText());
1135 m_localVariables.insertExpr(v);
1136 repaintNeeded = true;
1139 // repaint
1140 m_localVariables.setAutoUpdate(autoU);
1141 if (repaintNeeded && autoU && m_localVariables.isVisible())
1142 m_localVariables.repaint();
1145 void KDebugger::parseLocals(const char* output, QList<VarTree>& newVars)
1147 QList<VarTree> vars;
1148 m_d->parseLocals(output, vars);
1150 QString origName; /* used in renaming variables */
1151 while (vars.count() > 0)
1153 VarTree* variable = vars.take(0);
1154 // get some types
1155 variable->inferTypesOfChildren(*m_typeTable);
1157 * When gdb prints local variables, those from the innermost block
1158 * come first. We run through the list of already parsed variables
1159 * to find duplicates (ie. variables that hide local variables from
1160 * a surrounding block). We keep the name of the inner variable, but
1161 * rename those from the outer block so that, when the value is
1162 * updated in the window, the value of the variable that is
1163 * _visible_ changes the color!
1165 int block = 0;
1166 origName = variable->getText();
1167 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1168 if (variable->getText() == v->getText()) {
1169 // we found a duplicate, change name
1170 block++;
1171 QString newName = origName + " (" + QString().setNum(block) + ")";
1172 variable->setText(newName);
1175 newVars.append(variable);
1179 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1181 ASSERT(cmd->m_expr != 0);
1183 VarTree* variable = parseExpr(output, true);
1184 if (variable == 0)
1185 return false;
1187 // set expression "name"
1188 variable->setText(cmd->m_expr->getText());
1190 if (cmd->m_expr->m_varKind == VarTree::VKpointer) {
1192 * We must insert a dummy parent, because otherwise variable's value
1193 * would overwrite cmd->m_expr's value.
1195 VarTree* dummyParent = new VarTree(variable->getText(), VarTree::NKplain);
1196 dummyParent->m_varKind = VarTree::VKdummy;
1197 // the name of the parsed variable is the address of the pointer
1198 QString addr = "*" + cmd->m_expr->m_value;
1199 variable->setText(addr);
1200 variable->m_nameKind = VarTree::NKaddress;
1202 dummyParent->appendChild(variable);
1203 dummyParent->setDeleteChildren(true);
1204 TRACE("update ptr: " + cmd->m_expr->getText());
1205 cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent);
1206 delete dummyParent;
1207 } else {
1208 TRACE("update expr: " + cmd->m_expr->getText());
1209 cmd->m_exprWnd->updateExpr(cmd->m_expr, variable);
1210 delete variable;
1213 evalExpressions(); /* enqueue dereferenced pointers */
1215 return true;
1218 VarTree* KDebugger::parseExpr(const char* output, bool wantErrorValue)
1220 VarTree* variable;
1222 // check for error conditions
1223 bool goodValue = m_d->parsePrintExpr(output, wantErrorValue, variable);
1225 if (variable != 0 && goodValue)
1227 // get some types
1228 variable->inferTypesOfChildren(*m_typeTable);
1230 return variable;
1233 // parse the output of bt
1234 void KDebugger::handleBacktrace(const char* output)
1236 // reduce flicker
1237 m_btWindow.setAutoUpdate(false);
1239 m_btWindow.clear();
1241 QList<StackFrame> stack;
1242 m_d->parseBackTrace(output, stack);
1244 if (stack.count() > 0) {
1245 StackFrame* frm = stack.take(0);
1246 // first frame must set PC
1247 // note: frm->lineNo is zero-based
1248 emit updatePC(frm->fileName, frm->lineNo, frm->address, frm->frameNo);
1250 do {
1251 QString func;
1252 if (frm->var != 0)
1253 func = frm->var->getText();
1254 else
1255 func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1256 m_btWindow.insertItem(func);
1257 TRACE("frame " + func + " (" + frm->fileName + ":" +
1258 QString().setNum(frm->lineNo+1) + ")");
1259 delete frm;
1261 while ((frm = stack.take()) != 0);
1264 m_btWindow.setAutoUpdate(true);
1265 m_btWindow.repaint();
1268 void KDebugger::gotoFrame(int frame)
1270 m_d->executeCmd(DCframe, frame);
1273 void KDebugger::handleFrameChange(const char* output)
1275 QString fileName;
1276 int frameNo;
1277 int lineNo;
1278 DbgAddr address;
1279 if (m_d->parseFrameChange(output, frameNo, fileName, lineNo, address)) {
1280 /* lineNo can be negative here if we can't find a file name */
1281 emit updatePC(fileName, lineNo, address, frameNo);
1282 } else {
1283 emit updatePC(fileName, -1, address, frameNo);
1287 void KDebugger::evalExpressions()
1289 // evaluate expressions in the following order:
1290 // watch expressions
1291 // pointers in local variables
1292 // pointers in watch expressions
1293 // types in local variables
1294 // types in watch expressions
1295 // pointers in 'this'
1296 // types in 'this'
1298 VarTree* exprItem = m_watchEvalExpr.first();
1299 if (exprItem != 0) {
1300 m_watchEvalExpr.remove();
1301 QString expr = exprItem->computeExpr();
1302 TRACE("watch expr: " + expr);
1303 CmdQueueItem* cmd = m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverride);
1304 // remember which expr this was
1305 cmd->m_expr = exprItem;
1306 cmd->m_exprWnd = &m_watchVariables;
1307 } else {
1308 ExprWnd* wnd;
1309 VarTree* exprItem;
1310 #define POINTER(widget) \
1311 wnd = &widget; \
1312 exprItem = widget.nextUpdatePtr(); \
1313 if (exprItem != 0) goto pointer
1314 #define STRUCT(widget) \
1315 wnd = &widget; \
1316 exprItem = widget.nextUpdateStruct(); \
1317 if (exprItem != 0) goto ustruct
1318 #define TYPE(widget) \
1319 wnd = &widget; \
1320 exprItem = widget.nextUpdateType(); \
1321 if (exprItem != 0) goto type
1322 repeat:
1323 POINTER(m_localVariables);
1324 POINTER(m_watchVariables);
1325 STRUCT(m_localVariables);
1326 STRUCT(m_watchVariables);
1327 TYPE(m_localVariables);
1328 TYPE(m_watchVariables);
1329 #undef POINTER
1330 #undef STRUCT
1331 #undef TYPE
1332 return;
1334 pointer:
1335 // we have an expression to send
1336 dereferencePointer(wnd, exprItem, false);
1337 return;
1339 ustruct:
1340 // paranoia
1341 if (exprItem->m_type == 0 || exprItem->m_type == TypeInfo::unknownType())
1342 goto repeat;
1343 evalInitialStructExpression(exprItem, wnd, false);
1344 return;
1346 type:
1348 * Sometimes a VarTree gets registered twice for a type update. So
1349 * it may happen that it has already been updated. Hence, we ignore
1350 * it here and go on to the next task.
1352 if (exprItem->m_type != 0)
1353 goto repeat;
1354 determineType(wnd, exprItem);
1358 void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem,
1359 bool immediate)
1361 ASSERT(exprItem->m_varKind == VarTree::VKpointer);
1363 QString expr = exprItem->computeExpr();
1364 TRACE("dereferencing pointer: " + expr);
1365 QString queueExpr = "*(" + expr + ")";
1366 CmdQueueItem* cmd;
1367 if (immediate) {
1368 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverrideMoreEqual);
1369 } else {
1370 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverride);
1372 // remember which expr this was
1373 cmd->m_expr = exprItem;
1374 cmd->m_exprWnd = wnd;
1377 void KDebugger::determineType(ExprWnd* wnd, VarTree* exprItem)
1379 ASSERT(exprItem->m_varKind == VarTree::VKstruct);
1381 QString expr = exprItem->computeExpr();
1382 TRACE("get type of: " + expr);
1383 CmdQueueItem* cmd;
1384 cmd = m_d->queueCmd(DCfindType, expr, DebuggerDriver::QMoverride);
1386 // remember which expr this was
1387 cmd->m_expr = exprItem;
1388 cmd->m_exprWnd = wnd;
1391 void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output)
1393 QString type;
1394 if (m_d->parseFindType(output, type))
1396 ASSERT(cmd != 0 && cmd->m_expr != 0);
1398 TypeInfo* info = m_typeTable->lookup(type);
1400 if (info == 0) {
1402 * We've asked gdb for the type of the expression in
1403 * cmd->m_expr, but it returned a name we don't know. The base
1404 * class (and member) types have been checked already (at the
1405 * time when we parsed that particular expression). Now it's
1406 * time to derive the type from the base classes as a last
1407 * resort.
1409 info = cmd->m_expr->inferTypeFromBaseClass();
1410 // if we found a type through this method, register an alias
1411 if (info != 0) {
1412 TRACE("infered alias: " + type);
1413 m_typeTable->registerAlias(type, info);
1416 if (info == 0) {
1417 TRACE("unknown type");
1418 cmd->m_expr->m_type = TypeInfo::unknownType();
1419 } else {
1420 cmd->m_expr->m_type = info;
1421 /* since this node has a new type, we get its value immediately */
1422 evalInitialStructExpression(cmd->m_expr, cmd->m_exprWnd, false);
1423 return;
1427 evalExpressions(); /* queue more of them */
1430 void KDebugger::handlePrintStruct(CmdQueueItem* cmd, const char* output)
1432 VarTree* var = cmd->m_expr;
1433 ASSERT(var != 0);
1434 ASSERT(var->m_varKind == VarTree::VKstruct);
1436 VarTree* partExpr;
1437 if (cmd->m_cmd != DCprintQStringStruct) {
1438 partExpr = parseExpr(output, false);
1439 } else {
1440 partExpr = m_d->parseQCharArray(output, false);
1442 bool errorValue =
1443 partExpr == 0 ||
1444 /* we only allow simple values at the moment */
1445 partExpr->childCount() != 0;
1447 QString partValue;
1448 if (errorValue)
1450 partValue = "???";
1451 } else {
1452 partValue = partExpr->m_value;
1454 delete partExpr;
1455 partExpr = 0;
1458 * Updating a struct value works like this: var->m_partialValue holds
1459 * the value that we have gathered so far (it's been initialized with
1460 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1461 * we append the printed result followed by the next
1462 * var->m_type->m_displayString to var->m_partialValue.
1464 * If the expression we just evaluated was a guard expression, and it
1465 * resulted in an error, we must not evaluate the real expression, but
1466 * go on to the next index. (We must still add the ??? to the value).
1468 * Next, if this was the length expression, we still have not seen the
1469 * real expression, but the length of a QString.
1471 ASSERT(var->m_exprIndex >= 0 && var->m_exprIndex <= typeInfoMaxExpr);
1473 if (errorValue || !var->m_exprIndexUseGuard)
1475 // add current partValue (which might be ???)
1476 #if QT_VERSION < 200
1477 var->m_partialValue.detach();
1478 #endif
1479 var->m_partialValue += partValue;
1480 var->m_exprIndex++; /* next part */
1481 var->m_exprIndexUseGuard = true;
1482 var->m_partialValue += var->m_type->m_displayString[var->m_exprIndex];
1484 else
1486 // this was a guard expression that succeeded
1487 // go for the real expression
1488 var->m_exprIndexUseGuard = false;
1491 /* go for more sub-expressions if needed */
1492 if (var->m_exprIndex < var->m_type->m_numExprs) {
1493 /* queue a new print command with quite high priority */
1494 evalStructExpression(var, cmd->m_exprWnd, true);
1495 return;
1498 cmd->m_exprWnd->updateStructValue(var);
1500 evalExpressions(); /* enqueue dereferenced pointers */
1503 /* queues the first printStruct command for a struct */
1504 void KDebugger::evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1506 var->m_exprIndex = 0;
1507 var->m_exprIndexUseGuard = true;
1508 var->m_partialValue = var->m_type->m_displayString[0];
1509 evalStructExpression(var, wnd, immediate);
1512 /* queues a printStruct command; var must have been initialized correctly */
1513 void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1515 QString base = var->computeExpr();
1516 QString exprFmt;
1517 if (var->m_exprIndexUseGuard) {
1518 exprFmt = var->m_type->m_guardStrings[var->m_exprIndex];
1519 if (exprFmt.isEmpty()) {
1520 // no guard, omit it and go to expression
1521 var->m_exprIndexUseGuard = false;
1524 if (!var->m_exprIndexUseGuard) {
1525 exprFmt = var->m_type->m_exprStrings[var->m_exprIndex];
1528 SIZED_QString(expr, exprFmt.length() + base.length() + 10);
1529 expr.sprintf(exprFmt, base.data());
1531 DbgCommand dbgCmd = DCprintStruct;
1532 // check if this is a QString::Data
1533 if (strncmp(expr, "/QString::Data ", 15) == 0)
1535 if (m_typeTable->parseQt2QStrings())
1537 expr = expr.mid(15, expr.length()); /* strip off /QString::Data */
1538 dbgCmd = DCprintQStringStruct;
1539 } else {
1541 * This should not happen: the type libraries should be set up
1542 * in a way that this can't happen. If this happens
1543 * nevertheless it means that, eg., kdecore was loaded but qt2
1544 * was not (only qt2 enables the QString feature).
1546 // TODO: remove this "print"; queue the next printStruct instead
1547 expr = "*0";
1549 } else {
1550 expr = expr;
1552 TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1553 CmdQueueItem* cmd = m_d->queueCmd(dbgCmd, expr,
1554 immediate ? DebuggerDriver::QMoverrideMoreEqual
1555 : DebuggerDriver::QMnormal);
1557 // remember which expression this was
1558 cmd->m_expr = var;
1559 cmd->m_exprWnd = wnd;
1562 /* removes expression from window */
1563 void KDebugger::removeExpr(ExprWnd* wnd, VarTree* var)
1565 if (var == 0)
1566 return;
1568 // must remove any references to var from command queues
1569 m_d->dequeueCmdByVar(var);
1571 wnd->removeExpr(var);
1574 void KDebugger::handleSharedLibs(const char* output)
1576 // delete all known libraries
1577 m_sharedLibs.clear();
1579 // parse the table of shared libraries
1580 m_d->parseSharedLibs(output, m_sharedLibs);
1581 m_sharedLibsListed = true;
1583 // get type libraries
1584 m_typeTable->loadLibTypes(m_sharedLibs);
1587 CmdQueueItem* KDebugger::loadCoreFile()
1589 return m_d->queueCmd(DCcorefile, m_corefile, DebuggerDriver::QMoverride);
1592 void KDebugger::slotLocalsExpanding(KTreeViewItem* item, bool& allow)
1594 exprExpandingHelper(&m_localVariables, item, allow);
1597 void KDebugger::slotWatchExpanding(KTreeViewItem* item, bool& allow)
1599 exprExpandingHelper(&m_watchVariables, item, allow);
1602 void KDebugger::exprExpandingHelper(ExprWnd* wnd, KTreeViewItem* item, bool&)
1604 VarTree* exprItem = static_cast<VarTree*>(item);
1605 if (exprItem->m_varKind != VarTree::VKpointer) {
1606 return;
1608 dereferencePointer(wnd, exprItem, true);
1611 // add the expression in the edit field to the watch expressions
1612 void KDebugger::addWatch(const QString& t)
1614 QString expr = t.stripWhiteSpace();
1615 if (expr.isEmpty())
1616 return;
1617 VarTree* exprItem = new VarTree(expr, VarTree::NKplain);
1618 m_watchVariables.insertExpr(exprItem);
1620 // if we are boring ourselves, send down the command
1621 if (m_programActive) {
1622 m_watchEvalExpr.append(exprItem);
1623 if (m_d->isIdle()) {
1624 evalExpressions();
1629 // delete a toplevel watch expression
1630 void KDebugger::slotDeleteWatch()
1632 // delete only allowed while debugger is idle; or else we might delete
1633 // the very expression the debugger is currently working on...
1634 if (!m_d->isIdle())
1635 return;
1637 int index = m_watchVariables.currentItem();
1638 if (index < 0)
1639 return;
1641 VarTree* item = static_cast<VarTree*>(m_watchVariables.itemAt(index));
1642 if (!item->isToplevelExpr())
1643 return;
1645 // remove the variable from the list to evaluate
1646 if (m_watchEvalExpr.findRef(item) >= 0) {
1647 m_watchEvalExpr.remove();
1649 removeExpr(&m_watchVariables, item);
1650 // item is invalid at this point!
1653 void KDebugger::startAnimation(bool fast)
1655 int interval = fast ? 50 : 150;
1656 if (!m_animationTimer.isActive()) {
1657 m_animationTimer.start(interval);
1658 } else if (m_animationInterval != interval) {
1659 m_animationTimer.changeInterval(interval);
1661 m_animationInterval = interval;
1664 void KDebugger::stopAnimation()
1666 if (m_animationTimer.isActive()) {
1667 m_animationTimer.stop();
1668 m_animationInterval = 0;
1672 void KDebugger::slotUpdateAnimation()
1674 if (m_d->isIdle()) {
1675 stopAnimation();
1676 } else {
1678 * Slow animation while program is stopped (i.e. while variables
1679 * are displayed)
1681 bool slow = isReady() && m_programActive && !m_programRunning;
1682 startAnimation(!slow);
1686 void KDebugger::handleRegisters(const char* output)
1688 QList<RegisterInfo> regs;
1689 m_d->parseRegisters(output, regs);
1691 emit registersChanged(regs);
1693 // delete them all
1694 regs.setAutoDelete(true);
1698 * The output of the DCbreak* commands has more accurate information about
1699 * the file and the line number.
1701 void KDebugger::newBreakpoint(const char* output)
1703 int id;
1704 QString file;
1705 int lineNo;
1706 if (!m_d->parseBreakpoint(output, id, file, lineNo))
1707 return;
1709 // see if it is new
1710 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1711 if (m_brkpts[i]->id == id) {
1712 // not new; update
1713 m_brkpts[i]->fileName = file;
1714 m_brkpts[i]->lineNo = lineNo;
1715 return;
1718 // yes, new
1719 Breakpoint* bp = new Breakpoint;
1720 bp->id = id;
1721 bp->temporary = false;
1722 bp->enabled = true;
1723 bp->hitCount = 0;
1724 bp->ignoreCount = 0;
1725 bp->fileName = file;
1726 bp->lineNo = lineNo;
1727 int n = m_brkpts.size();
1728 m_brkpts.resize(n+1);
1729 m_brkpts[n] = bp;
1732 void KDebugger::updateBreakList(const char* output)
1734 // get the new list
1735 QList<Breakpoint> brks;
1736 brks.setAutoDelete(false);
1737 m_d->parseBreakList(output, brks);
1739 // merge new information into existing breakpoints
1741 QArray<Breakpoint*> oldbrks = m_brkpts;
1743 // move parsed breakpoints into m_brkpts
1744 m_brkpts.detach();
1745 m_brkpts.resize(brks.count());
1746 int n = 0;
1747 for (Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
1749 m_brkpts[n++] = bp;
1752 // go through all old breakpoints
1753 for (int i = oldbrks.size()-1; i >= 0; i--) {
1754 // is this one still alive?
1755 for (int j = m_brkpts.size()-1; j >= 0; j--)
1757 if (m_brkpts[j]->id == oldbrks[i]->id) {
1758 // yes, it is
1759 // keep accurate location
1760 m_brkpts[j]->fileName = oldbrks[i]->fileName;
1761 m_brkpts[j]->lineNo = oldbrks[i]->lineNo;
1762 break;
1767 // delete old breakpoints
1768 for (int i = oldbrks.size()-1; i >= 0; i--) {
1769 delete oldbrks[i];
1772 emit breakpointsChanged();
1775 // look if there is at least one temporary breakpoint
1776 // or a watchpoint
1777 bool KDebugger::stopMayChangeBreakList() const
1779 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1780 Breakpoint* bp = m_brkpts[i];
1781 if (bp->temporary || bp->type == Breakpoint::watchpoint)
1782 return true;
1784 return false;
1787 Breakpoint* KDebugger::breakpointByFilePos(QString file, int lineNo,
1788 const DbgAddr& address)
1790 // look for exact file name match
1791 int i;
1792 for (i = m_brkpts.size()-1; i >= 0; i--) {
1793 if (m_brkpts[i]->lineNo == lineNo &&
1794 m_brkpts[i]->fileName == file &&
1795 (address.isEmpty() || m_brkpts[i]->address == address))
1797 return m_brkpts[i];
1800 // not found, so try basename
1801 // strip off directory part of file name
1802 int offset = file.findRev("/");
1803 #if QT_VERSION < 200
1804 file.detach();
1805 #endif
1806 file.remove(0, offset+1);
1808 for (i = m_brkpts.size()-1; i >= 0; i--) {
1809 // get base name of breakpoint's file
1810 QString basename = m_brkpts[i]->fileName;
1811 int offset = basename.findRev("/");
1812 if (offset >= 0) {
1813 #if QT_VERSION < 200
1814 basename.detach();
1815 #endif
1816 basename.remove(0, offset+1);
1819 if (m_brkpts[i]->lineNo == lineNo &&
1820 basename == file &&
1821 (address.isEmpty() || m_brkpts[i]->address == address))
1823 return m_brkpts[i];
1827 // not found
1828 return 0;
1831 void KDebugger::slotValuePopup(const QString& expr)
1833 // search the local variables for a match
1834 VarTree* v = m_localVariables.topLevelExprByName(expr);
1835 if (v == 0) {
1836 // not found, check watch expressions
1837 v = m_watchVariables.topLevelExprByName(expr);
1838 if (v == 0) {
1839 // nothing found; do nothing
1840 return;
1844 // construct the tip
1845 QString tip = v->getText() + " = ";
1846 if (!v->m_value.isEmpty())
1848 tip += v->m_value;
1850 else
1852 // no value: we use some hint
1853 switch (v->m_varKind) {
1854 case VarTree::VKstruct:
1855 tip += "{...}";
1856 break;
1857 case VarTree::VKarray:
1858 tip += "[...]";
1859 break;
1860 default:
1861 tip += "???";
1862 break;
1865 emit valuePopup(tip);
1868 void KDebugger::slotDisassemble(const QString& fileName, int lineNo)
1870 CmdQueueItem* cmd = m_d->queueCmd(DCinfoline, fileName, lineNo,
1871 DebuggerDriver::QMoverrideMoreEqual);
1872 cmd->m_fileName = fileName;
1873 cmd->m_lineNo = lineNo;
1876 void KDebugger::handleInfoLine(CmdQueueItem* cmd, const char* output)
1878 QString addrFrom, addrTo;
1879 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
1880 // got the address range, now get the real code
1881 CmdQueueItem* c = m_d->queueCmd(DCdisassemble, addrFrom, addrTo,
1882 DebuggerDriver::QMoverrideMoreEqual);
1883 c->m_fileName = cmd->m_fileName;
1884 c->m_lineNo = cmd->m_lineNo;
1885 } else {
1886 // no code
1887 QList<DisassembledCode> empty;
1888 emit disassembled(cmd->m_fileName, cmd->m_lineNo, empty);
1892 void KDebugger::handleDisassemble(CmdQueueItem* cmd, const char* output)
1894 QList<DisassembledCode> code;
1895 code.setAutoDelete(true);
1896 m_d->parseDisassemble(output, code);
1897 emit disassembled(cmd->m_fileName, cmd->m_lineNo, code);
1900 void KDebugger::handleThreadList(const char* output)
1902 QList<ThreadInfo> threads;
1903 threads.setAutoDelete(true);
1904 m_d->parseThreadList(output, threads);
1905 emit threadsChanged(threads);
1908 void KDebugger::setThread(int id)
1910 m_d->queueCmd(DCthread, id, DebuggerDriver::QMoverrideMoreEqual);
1913 void KDebugger::setMemoryExpression(const QString& memexpr)
1915 m_memoryExpression = memexpr;
1917 // queue the new expression
1918 if (!m_memoryExpression.isEmpty() &&
1919 isProgramActive() &&
1920 !isProgramRunning())
1922 queueMemoryDump(true);
1926 void KDebugger::queueMemoryDump(bool immediate)
1928 m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat,
1929 immediate ? DebuggerDriver::QMoverrideMoreEqual :
1930 DebuggerDriver::QMoverride);
1933 void KDebugger::handleMemoryDump(const char* output)
1935 QList<MemoryDump> memdump;
1936 memdump.setAutoDelete(true);
1937 QString msg = m_d->parseMemoryDump(output, memdump);
1938 emit memoryDumpChanged(msg, memdump);
1942 #include "debugger.moc"