Latest updates from Keith for xsldbg 3.0.5.
[kdbg.git] / kdbg / debugger.cpp
blob9f6de19678a8cd8cf0e3a7a59b27177dbc1fb775
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 <qstringlist.h>
17 #include <kapp.h>
18 #include <ksimpleconfig.h>
19 #include <kconfig.h>
20 #include <klocale.h> /* i18n */
21 #include <kmessagebox.h>
22 #include <ctype.h>
23 #include <stdlib.h> /* strtol, atoi */
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h> /* sleep(3) */
26 #endif
27 #include "mydebug.h"
30 KDebugger::KDebugger(QWidget* parent,
31 ExprWnd* localVars,
32 ExprWnd* watchVars,
33 QListBox* backtrace) :
34 QObject(parent, "debugger"),
35 m_ttyLevel(ttyFull),
36 m_memoryFormat(MDTword | MDThex),
37 m_haveExecutable(false),
38 m_programActive(false),
39 m_programRunning(false),
40 m_sharedLibsListed(false),
41 m_typeTable(0),
42 m_programConfig(0),
43 m_d(0),
44 m_localVariables(*localVars),
45 m_watchVariables(*watchVars),
46 m_btWindow(*backtrace),
47 m_animationTimer(this),
48 m_animationInterval(0)
50 m_envVars.setAutoDelete(true);
52 connect(&m_localVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
53 SLOT(slotLocalsExpanding(KTreeViewItem*,bool&)));
54 connect(&m_watchVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
55 SLOT(slotWatchExpanding(KTreeViewItem*,bool&)));
57 connect(&m_btWindow, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
59 // animation
60 connect(&m_animationTimer, SIGNAL(timeout()), SIGNAL(animationTimeout()));
61 // special update of animation
62 connect(this, SIGNAL(updateUI()), SLOT(slotUpdateAnimation()));
64 emit updateUI();
67 KDebugger::~KDebugger()
69 if (m_programConfig != 0) {
70 saveProgramSettings();
71 m_programConfig->sync();
72 delete m_programConfig;
74 // delete breakpoint objects
75 for (int i = m_brkpts.size()-1; i >= 0; i--) {
76 delete m_brkpts[i];
79 delete m_typeTable;
83 void KDebugger::saveSettings(KConfig* /*config*/)
87 void KDebugger::restoreSettings(KConfig* /*config*/)
92 //////////////////////////////////////////////////////////////////////
93 // external interface
95 const char GeneralGroup[] = "General";
96 const char DebuggerCmdStr[] = "DebuggerCmdStr";
97 const char TTYLevelEntry[] = "TTYLevel";
98 const char KDebugger::DriverNameEntry[] = "DriverName";
100 bool KDebugger::debugProgram(const QString& name,
101 DebuggerDriver* driver)
103 if (m_d != 0 && m_d->isRunning())
105 QApplication::setOverrideCursor(waitCursor);
107 stopDriver();
109 QApplication::restoreOverrideCursor();
111 if (m_d->isRunning() || m_haveExecutable) {
112 /* timed out! We can't really do anything useful now */
113 TRACE("timed out while waiting for gdb to die!");
114 return false;
116 delete m_d;
117 m_d = 0;
120 // wire up the driver
121 connect(driver, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
122 this, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)));
123 connect(driver, SIGNAL(processExited(KProcess*)), SLOT(gdbExited(KProcess*)));
124 connect(driver, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
125 SLOT(parse(CmdQueueItem*,const char*)));
126 connect(driver, SIGNAL(wroteStdin(KProcess*)), SIGNAL(updateUI()));
127 connect(driver, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
128 connect(driver, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
129 connect(driver, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
131 // create the program settings object
132 openProgramConfig(name);
134 // get debugger command from per-program settings
135 if (m_programConfig != 0) {
136 m_programConfig->setGroup(GeneralGroup);
137 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
138 // get terminal emulation level
139 m_ttyLevel = TTYLevel(m_programConfig->readNumEntry(TTYLevelEntry, ttyFull));
141 // the rest is read in later in the handler of DCexecutable
143 m_d = driver;
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 != 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::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()
232 if (canSingleStep()) {
233 m_d->executeCmd(DCstep, true);
234 m_programRunning = true;
238 void KDebugger::programNext()
240 if (canSingleStep()) {
241 m_d->executeCmd(DCnext, true);
242 m_programRunning = true;
246 void KDebugger::programStepi()
248 if (canSingleStep()) {
249 m_d->executeCmd(DCstepi, true);
250 m_programRunning = true;
254 void KDebugger::programNexti()
256 if (canSingleStep()) {
257 m_d->executeCmd(DCnexti, true);
258 m_programRunning = true;
262 void KDebugger::programFinish()
264 if (canSingleStep()) {
265 m_d->executeCmd(DCfinish, true);
266 m_programRunning = true;
270 void KDebugger::programKill()
272 if (haveExecutable() && isProgramActive()) {
273 if (m_programRunning) {
274 m_d->interruptInferior();
276 // this is an emergency command; flush queues
277 m_d->flushCommands(true);
278 m_d->executeCmd(DCkill, true);
282 bool KDebugger::runUntil(const QString& fileName, int lineNo)
284 if (isReady() && m_programActive && !m_programRunning) {
285 // strip off directory part of file name
286 QString file = fileName;
287 int offset = file.findRev("/");
288 if (offset >= 0) {
289 file.remove(0, offset+1);
291 m_d->executeCmd(DCuntil, file, lineNo, true);
292 m_programRunning = true;
293 return true;
294 } else {
295 return false;
299 void KDebugger::programBreak()
301 if (m_haveExecutable && m_programRunning) {
302 m_d->interruptInferior();
306 void KDebugger::programArgs(QWidget* parent)
308 if (m_haveExecutable) {
309 QStringList allOptions = m_d->boolOptionList();
310 PgmArgs dlg(parent, m_executable, m_envVars, allOptions);
311 dlg.setArgs(m_programArgs);
312 dlg.setWd(m_programWD);
313 dlg.setOptions(m_boolOptions);
314 if (dlg.exec()) {
315 updateProgEnvironment(dlg.args(), dlg.wd(),
316 dlg.envVars(), dlg.options());
321 void KDebugger::programSettings(QWidget* parent)
323 if (!m_haveExecutable)
324 return;
326 ProgramSettings dlg(parent, m_executable);
328 dlg.m_chooseDriver.setDebuggerCmd(m_debuggerCmd);
329 dlg.m_output.setTTYLevel(m_ttyLevel);
331 if (dlg.exec() == QDialog::Accepted)
333 m_debuggerCmd = dlg.m_chooseDriver.debuggerCmd();
334 m_ttyLevel = TTYLevel(dlg.m_output.ttyLevel());
338 bool KDebugger::setBreakpoint(QString file, int lineNo,
339 const DbgAddr& address, bool temporary)
341 if (!isReady()) {
342 return false;
345 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
346 if (bp == 0)
349 * No such breakpoint, so set a new one. If we have an address, we
350 * set the breakpoint exactly there. Otherwise we use the file name
351 * plus line no.
353 if (address.isEmpty())
355 // strip off directory part of file name
356 int offset = file.findRev("/");
357 if (offset >= 0) {
358 file.remove(0, offset+1);
360 m_d->executeCmd(temporary ? DCtbreakline : DCbreakline,
361 file, lineNo);
363 else
365 m_d->executeCmd(temporary ? DCtbreakaddr : DCbreakaddr,
366 address.asString());
369 else
372 * If the breakpoint is disabled, enable it; if it's enabled,
373 * delete that breakpoint.
375 if (bp->enabled) {
376 m_d->executeCmd(DCdelete, bp->id);
377 } else {
378 m_d->executeCmd(DCenable, bp->id);
381 return true;
384 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo,
385 const DbgAddr& address)
387 if (!isReady()) {
388 return false;
391 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
392 if (bp == 0)
393 return true;
395 // toggle enabled/disabled state
396 if (bp->enabled) {
397 m_d->executeCmd(DCdisable, bp->id);
398 } else {
399 m_d->executeCmd(DCenable, bp->id);
401 return true;
404 bool KDebugger::canSingleStep()
406 return isReady() && m_programActive && !m_programRunning;
409 bool KDebugger::canChangeBreakpoints()
411 return isReady() && !m_programRunning;
414 bool KDebugger::isReady() const
416 return m_haveExecutable &&
417 m_d != 0 && m_d->canExecuteImmediately();
420 bool KDebugger::isIdle() const
422 return m_d == 0 || m_d->isIdle();
426 //////////////////////////////////////////////////////////
427 // debugger driver
429 bool KDebugger::startDriver()
431 emit debuggerStarting(); /* must set m_inferiorTerminal */
434 * If the per-program command string is empty, use the global setting
435 * (which might also be empty, in which case the driver uses its
436 * default).
438 m_explicitKill = false;
439 if (!m_d->startup(m_debuggerCmd)) {
440 return false;
444 * If we have an output terminal, we use it. Otherwise we will run the
445 * program with input and output redirected to /dev/null. Other
446 * redirections are also necessary depending on the tty emulation
447 * level.
449 int redirect = RDNstdin|RDNstdout|RDNstderr; /* redirect everything */
450 if (!m_inferiorTerminal.isEmpty()) {
451 switch (m_ttyLevel) {
452 default:
453 case ttyNone:
454 // redirect everything
455 break;
456 case ttySimpleOutputOnly:
457 redirect = RDNstdin;
458 break;
459 case ttyFull:
460 redirect = 0;
461 break;
464 m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
466 return true;
469 void KDebugger::stopDriver()
471 m_explicitKill = true;
473 if (m_attachedPid.isEmpty()) {
474 m_d->terminate();
475 } else {
476 m_d->detachAndTerminate();
480 * We MUST wait until the slot gdbExited() has been called. But to
481 * avoid a deadlock, we wait only for some certain maximum time. Should
482 * this timeout be reached, the only reasonable thing one could do then
483 * is exiting kdbg.
485 kapp->processEvents(1000); /* ideally, this will already shut it down */
486 int maxTime = 20; /* about 20 seconds */
487 while (m_haveExecutable && maxTime > 0) {
488 // give gdb time to die (and send a SIGCLD)
489 ::sleep(1);
490 --maxTime;
491 kapp->processEvents(1000);
495 void KDebugger::gdbExited(KProcess*)
498 * Save settings, but only if gdb has already processed "info line
499 * main", otherwise we would save an empty config file, because it
500 * isn't read in until then!
502 if (m_programConfig != 0) {
503 if (m_haveExecutable) {
504 saveProgramSettings();
505 m_programConfig->sync();
507 delete m_programConfig;
508 m_programConfig = 0;
511 // erase types
512 delete m_typeTable;
513 m_typeTable = 0;
515 if (m_explicitKill) {
516 TRACE(m_d->driverName() + " exited normally");
517 } else {
518 QString msg = i18n("%1 exited unexpectedly.\n"
519 "Restart the session (e.g. with File|Executable).");
520 KMessageBox::error(parentWidget(), msg.arg(m_d->driverName()));
523 // reset state
524 m_haveExecutable = false;
525 m_executable = "";
526 m_programActive = false;
527 m_programRunning = false;
528 m_explicitKill = false;
529 m_debuggerCmd = QString(); /* use global setting at next start! */
530 m_attachedPid = QString(); /* we are no longer attached to a process */
531 m_ttyLevel = ttyFull;
533 // stop gear wheel and erase PC
534 stopAnimation();
535 emit updatePC(QString(), -1, DbgAddr(), 0);
538 QString KDebugger::getConfigForExe(const QString& name)
540 QFileInfo fi(name);
541 QString pgmConfigFile = fi.dirPath(true);
542 if (!pgmConfigFile.isEmpty()) {
543 pgmConfigFile += '/';
545 pgmConfigFile += ".kdbgrc." + fi.fileName();
546 TRACE("program config file = " + pgmConfigFile);
547 return pgmConfigFile;
550 void KDebugger::openProgramConfig(const QString& name)
552 ASSERT(m_programConfig == 0);
554 QString pgmConfigFile = getConfigForExe(name);
555 // check whether we can write to the file
556 QFile file(pgmConfigFile);
557 bool readonly = true;
558 bool openit = true;
559 if (file.open(IO_ReadWrite)) { /* don't truncate! */
560 readonly = false;
561 // the file exists now
562 } else if (!file.open(IO_ReadOnly)) {
563 /* file does not exist and cannot be created: don't use it */
564 openit = false;
566 if (openit) {
567 m_programConfig = new KSimpleConfig(pgmConfigFile, readonly);
571 const char EnvironmentGroup[] = "Environment";
572 const char WatchGroup[] = "Watches";
573 const char FileVersion[] = "FileVersion";
574 const char ProgramArgs[] = "ProgramArgs";
575 const char WorkingDirectory[] = "WorkingDirectory";
576 const char OptionsSelected[] = "OptionsSelected";
577 const char Variable[] = "Var%d";
578 const char Value[] = "Value%d";
579 const char ExprFmt[] = "Expr%d";
581 void KDebugger::saveProgramSettings()
583 ASSERT(m_programConfig != 0);
584 m_programConfig->setGroup(GeneralGroup);
585 m_programConfig->writeEntry(FileVersion, 1);
586 m_programConfig->writeEntry(ProgramArgs, m_programArgs);
587 m_programConfig->writeEntry(WorkingDirectory, m_programWD);
588 m_programConfig->writeEntry(OptionsSelected, m_boolOptions);
589 m_programConfig->writeEntry(DebuggerCmdStr, m_debuggerCmd);
590 m_programConfig->writeEntry(TTYLevelEntry, int(m_ttyLevel));
591 QString driverName;
592 if (m_d != 0)
593 driverName = m_d->driverName();
594 m_programConfig->writeEntry(DriverNameEntry, driverName);
596 // write environment variables
597 m_programConfig->deleteGroup(EnvironmentGroup);
598 m_programConfig->setGroup(EnvironmentGroup);
599 QDictIterator<EnvVar> it = m_envVars;
600 EnvVar* var;
601 QString varName;
602 QString varValue;
603 for (int i = 0; (var = it) != 0; ++it, ++i) {
604 varName.sprintf(Variable, i);
605 varValue.sprintf(Value, i);
606 m_programConfig->writeEntry(varName, it.currentKey());
607 m_programConfig->writeEntry(varValue, var->value);
610 saveBreakpoints(m_programConfig);
612 // watch expressions
613 // first get rid of whatever was in this group
614 m_programConfig->deleteGroup(WatchGroup);
615 // then start a new group
616 m_programConfig->setGroup(WatchGroup);
617 KTreeViewItem* item = m_watchVariables.itemAt(0);
618 int watchNum = 0;
619 for (; item != 0; item = item->getSibling(), ++watchNum) {
620 varName.sprintf(ExprFmt, watchNum);
621 m_programConfig->writeEntry(varName, item->getText());
624 // give others a chance
625 emit saveProgramSpecific(m_programConfig);
628 void KDebugger::restoreProgramSettings()
630 ASSERT(m_programConfig != 0);
631 m_programConfig->setGroup(GeneralGroup);
633 * We ignore file version for now we will use it in the future to
634 * distinguish different versions of this configuration file.
636 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
637 // m_ttyLevel has been read in already
638 QString pgmArgs = m_programConfig->readEntry(ProgramArgs);
639 QString pgmWd = m_programConfig->readEntry(WorkingDirectory);
640 QStringList boolOptions = m_programConfig->readListEntry(OptionsSelected);
641 m_boolOptions = QStringList();
643 // read environment variables
644 m_programConfig->setGroup(EnvironmentGroup);
645 m_envVars.clear();
646 QDict<EnvVar> pgmVars;
647 EnvVar* var;
648 QString varName;
649 QString varValue;
650 for (int i = 0;; ++i) {
651 varName.sprintf(Variable, i);
652 varValue.sprintf(Value, i);
653 if (!m_programConfig->hasKey(varName)) {
654 /* entry not present, assume that we've hit them all */
655 break;
657 QString name = m_programConfig->readEntry(varName);
658 if (name.isEmpty()) {
659 // skip empty names
660 continue;
662 var = new EnvVar;
663 var->value = m_programConfig->readEntry(varValue);
664 var->status = EnvVar::EVnew;
665 pgmVars.insert(name, var);
668 updateProgEnvironment(pgmArgs, pgmWd, pgmVars, boolOptions);
670 restoreBreakpoints(m_programConfig);
672 // watch expressions
673 m_programConfig->setGroup(WatchGroup);
674 m_watchVariables.clear();
675 for (int i = 0;; ++i) {
676 varName.sprintf(ExprFmt, i);
677 if (!m_programConfig->hasKey(varName)) {
678 /* entry not present, assume that we've hit them all */
679 break;
681 QString expr = m_programConfig->readEntry(varName);
682 if (expr.isEmpty()) {
683 // skip empty expressions
684 continue;
686 addWatch(expr);
689 // give others a chance
690 emit restoreProgramSpecific(m_programConfig);
694 * Breakpoints are saved one per group.
696 const char BPGroup[] = "Breakpoint %d";
697 const char File[] = "File";
698 const char Line[] = "Line";
699 const char Address[] = "Address";
700 const char Temporary[] = "Temporary";
701 const char Enabled[] = "Enabled";
702 const char Condition[] = "Condition";
704 void KDebugger::saveBreakpoints(KSimpleConfig* config)
706 QString groupName;
707 int i = 0;
708 for (uint j = 0; j < m_brkpts.size(); j++) {
709 Breakpoint* bp = m_brkpts[j];
710 if (bp->type == Breakpoint::watchpoint)
711 continue; /* don't save watchpoints */
712 groupName.sprintf(BPGroup, i++);
713 config->setGroup(groupName);
714 if (!bp->fileName.isEmpty()) {
715 config->writeEntry(File, bp->fileName);
716 config->writeEntry(Line, bp->lineNo);
718 * Addresses are hardly correct across sessions, so we remove
719 * it since we have a file name and line number.
721 config->deleteEntry(Address, false);
722 } else {
723 config->writeEntry(Address, bp->address.asString());
724 /* remove remmants */
725 config->deleteEntry(File, false);
726 config->deleteEntry(Line, false);
728 config->writeEntry(Temporary, bp->temporary);
729 config->writeEntry(Enabled, bp->enabled);
730 if (bp->condition.isEmpty())
731 config->deleteEntry(Condition, false);
732 else
733 config->writeEntry(Condition, bp->condition);
734 // we do not save the ignore count
736 // delete remaining groups
737 // we recognize that a group is present if there is an Enabled entry
738 for (;; i++) {
739 groupName.sprintf(BPGroup, i);
740 config->setGroup(groupName);
741 if (!config->hasKey(Enabled)) {
742 /* group not present, assume that we've hit them all */
743 break;
745 config->deleteGroup(groupName);
749 void KDebugger::restoreBreakpoints(KSimpleConfig* config)
751 QString groupName;
752 QString fileName;
753 QString address;
754 int lineNo;
755 bool enabled, temporary;
756 QString condition;
758 * We recognize the end of the list if there is no Enabled entry
759 * present.
761 for (int i = 0;; i++) {
762 groupName.sprintf(BPGroup, i);
763 config->setGroup(groupName);
764 if (!config->hasKey(Enabled)) {
765 /* group not present, assume that we've hit them all */
766 break;
768 fileName = config->readEntry(File);
769 lineNo = config->readNumEntry(Line, -1);
770 address = config->readEntry(Address);
771 if ((fileName.isEmpty() || lineNo < 0) && address.isEmpty())
772 continue;
773 enabled = config->readBoolEntry(Enabled, true);
774 temporary = config->readBoolEntry(Temporary, false);
775 condition = config->readEntry(Condition);
777 * Add the breakpoint. We assume that we have started a new
778 * instance of gdb, because we assign the breakpoint ids ourselves,
779 * starting with 1. Then we use this id to disable the breakpoint,
780 * if necessary. If this assignment of ids doesn't work, (maybe
781 * because this isn't a fresh gdb at all), we disable the wrong
782 * breakpoint! Oh well... for now it works.
784 if (!fileName.isEmpty()) {
785 m_d->executeCmd(temporary ? DCtbreakline : DCbreakline,
786 fileName, lineNo);
787 } else {
788 m_d->executeCmd(temporary ? DCtbreakaddr : DCbreakaddr,
789 address);
791 if (!enabled) {
792 m_d->executeCmd(DCdisable, i+1);
794 if (!condition.isEmpty()) {
795 m_d->executeCmd(DCcondition, condition, i+1);
798 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
802 // parse output of command cmd
803 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
805 ASSERT(cmd != 0); /* queue mustn't be empty */
807 TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
809 switch (cmd->m_cmd) {
810 case DCtargetremote:
811 // the output (if any) is uninteresting
812 case DCsetargs:
813 case DCtty:
814 // there is no output
815 case DCsetenv:
816 case DCunsetenv:
817 case DCsetoption:
818 /* if value is empty, we see output, but we don't care */
819 break;
820 case DCcd:
821 /* display gdb's message in the status bar */
822 m_d->parseChangeWD(output, m_statusMessage);
823 emit updateStatusMessage();
824 break;
825 case DCinitialize:
826 break;
827 case DCexecutable:
828 if (m_d->parseChangeExecutable(output, m_statusMessage))
830 // success; restore breakpoints etc.
831 if (m_programConfig != 0) {
832 restoreProgramSettings();
834 // load file containing main() or core file
835 if (m_corefile.isEmpty()) {
836 if (m_remoteDevice.isEmpty())
837 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
838 } else {
839 // load core file
840 loadCoreFile();
842 if (!m_statusMessage.isEmpty())
843 emit updateStatusMessage();
844 } else {
845 QString msg = m_d->driverName() + ": " + m_statusMessage;
846 KMessageBox::sorry(parentWidget(), msg);
847 m_executable = "";
848 m_corefile = ""; /* don't process core file */
849 m_haveExecutable = false;
851 break;
852 case DCcorefile:
853 // in any event we have an executable at this point
854 m_haveExecutable = true;
855 if (m_d->parseCoreFile(output)) {
856 // loading a core is like stopping at a breakpoint
857 m_programActive = true;
858 handleRunCommands(output);
859 // do not reset m_corefile
860 } else {
861 // report error
862 QString msg = m_d->driverName() + ": " + QString(output);
863 KMessageBox::sorry(parentWidget(), msg);
865 // if core file was loaded from command line, revert to info line main
866 if (!cmd->m_byUser) {
867 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
869 m_corefile = QString(); /* core file not available any more */
871 break;
872 case DCinfolinemain:
873 // ignore the output, marked file info follows
874 m_haveExecutable = true;
875 break;
876 case DCinfolocals:
877 // parse local variables
878 if (output[0] != '\0') {
879 handleLocals(output);
881 break;
882 case DCinforegisters:
883 handleRegisters(output);
884 break;
885 case DCexamine:
886 handleMemoryDump(output);
887 break;
888 case DCinfoline:
889 handleInfoLine(cmd, output);
890 break;
891 case DCdisassemble:
892 handleDisassemble(cmd, output);
893 break;
894 case DCframe:
895 handleFrameChange(output);
896 updateAllExprs();
897 break;
898 case DCbt:
899 handleBacktrace(output);
900 updateAllExprs();
901 break;
902 case DCprint:
903 handlePrint(cmd, output);
904 break;
905 case DCattach:
906 case DCrun:
907 case DCcont:
908 case DCstep:
909 case DCstepi:
910 case DCnext:
911 case DCnexti:
912 case DCfinish:
913 case DCuntil:
914 case DCthread:
915 handleRunCommands(output);
916 break;
917 case DCkill:
918 m_programRunning = m_programActive = false;
919 // erase PC
920 emit updatePC(QString(), -1, DbgAddr(), 0);
921 break;
922 case DCbreaktext:
923 case DCbreakline:
924 case DCtbreakline:
925 case DCbreakaddr:
926 case DCtbreakaddr:
927 case DCwatchpoint:
928 newBreakpoint(output);
929 // fall through
930 case DCdelete:
931 case DCenable:
932 case DCdisable:
933 // these commands need immediate response
934 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverrideMoreEqual);
935 break;
936 case DCinfobreak:
937 // note: this handler must not enqueue a command, since
938 // DCinfobreak is used at various different places.
939 updateBreakList(output);
940 emit lineItemsChanged();
941 break;
942 case DCfindType:
943 handleFindType(cmd, output);
944 break;
945 case DCprintStruct:
946 case DCprintQStringStruct:
947 handlePrintStruct(cmd, output);
948 break;
949 case DCinfosharedlib:
950 handleSharedLibs(output);
951 break;
952 case DCcondition:
953 case DCignore:
954 // we are not interested in the output
955 break;
956 case DCinfothreads:
957 handleThreadList(output);
958 break;
962 void KDebugger::backgroundUpdate()
965 * If there are still expressions that need to be updated, then do so.
967 if (m_programActive)
968 evalExpressions();
971 void KDebugger::handleRunCommands(const char* output)
973 uint flags = m_d->parseProgramStopped(output, m_statusMessage);
974 emit updateStatusMessage();
976 m_programActive = flags & DebuggerDriver::SFprogramActive;
978 // refresh files if necessary
979 if (flags & DebuggerDriver::SFrefreshSource) {
980 TRACE("re-reading files");
981 emit executableUpdated();
985 * If we stopped at a breakpoint, we must update the breakpoint list
986 * because the hit count changes. Also, if the breakpoint was temporary
987 * it would go away now.
989 if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
990 stopMayChangeBreakList())
992 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
996 * If we haven't listed the shared libraries yet, do so. We must do
997 * this before we emit any commands that list variables, since the type
998 * libraries depend on the shared libraries.
1000 if (!m_sharedLibsListed) {
1001 // must be a high-priority command!
1002 m_d->executeCmd(DCinfosharedlib);
1005 // get the backtrace if the program is running
1006 if (m_programActive) {
1007 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
1008 } else {
1009 // program finished: erase PC
1010 emit updatePC(QString(), -1, DbgAddr(), 0);
1011 // dequeue any commands in the queues
1012 m_d->flushCommands();
1015 /* Update threads list */
1016 if (flags & DebuggerDriver::SFrefreshThreads) {
1017 m_d->queueCmd(DCinfothreads, DebuggerDriver::QMoverride);
1020 m_programRunning = false;
1021 emit programStopped();
1024 void KDebugger::slotInferiorRunning()
1026 m_programRunning = true;
1029 void KDebugger::updateAllExprs()
1031 if (!m_programActive)
1032 return;
1034 // retrieve local variables
1035 m_d->queueCmd(DCinfolocals, DebuggerDriver::QMoverride);
1037 // retrieve registers
1038 m_d->queueCmd(DCinforegisters, DebuggerDriver::QMoverride);
1040 // get new memory dump
1041 if (!m_memoryExpression.isEmpty()) {
1042 queueMemoryDump(false);
1045 // update watch expressions
1046 KTreeViewItem* item = m_watchVariables.itemAt(0);
1047 for (; item != 0; item = item->getSibling()) {
1048 m_watchEvalExpr.append(static_cast<VarTree*>(item));
1052 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
1053 const QDict<EnvVar>& newVars,
1054 const QStringList& newOptions)
1056 m_programArgs = args;
1057 m_d->executeCmd(DCsetargs, m_programArgs);
1058 TRACE("new pgm args: " + m_programArgs + "\n");
1060 m_programWD = wd.stripWhiteSpace();
1061 if (!m_programWD.isEmpty()) {
1062 m_d->executeCmd(DCcd, m_programWD);
1063 TRACE("new wd: " + m_programWD + "\n");
1066 // update environment variables
1067 QDictIterator<EnvVar> it = newVars;
1068 EnvVar* val;
1069 for (; (val = it) != 0; ++it) {
1070 QString var = it.currentKey();
1071 switch (val->status) {
1072 case EnvVar::EVnew:
1073 m_envVars.insert(var, val);
1074 // fall thru
1075 case EnvVar::EVdirty:
1076 // the value must be in our list
1077 ASSERT(m_envVars[var] == val);
1078 // update value
1079 m_d->executeCmd(DCsetenv, var, val->value);
1080 break;
1081 case EnvVar::EVdeleted:
1082 // must be in our list
1083 ASSERT(m_envVars[var] == val);
1084 // delete value
1085 m_d->executeCmd(DCunsetenv, var);
1086 m_envVars.remove(var);
1087 break;
1088 default:
1089 ASSERT(false);
1090 case EnvVar::EVclean:
1091 // variable not changed
1092 break;
1096 // update options
1097 QStringList::ConstIterator oi;
1098 for (oi = newOptions.begin(); oi != newOptions.end(); ++oi)
1100 if (m_boolOptions.findIndex(*oi) < 0) {
1101 // the options is currently not set, so set it
1102 m_d->executeCmd(DCsetoption, *oi, 1);
1103 } else {
1104 // option is set, no action required, but move it to the end
1105 m_boolOptions.remove(*oi);
1107 m_boolOptions.append(*oi);
1110 * Now all options that should be set are at the end of m_boolOptions.
1111 * If some options need to be unset, they are at the front of the list.
1112 * Here we unset and remove them.
1114 while (m_boolOptions.count() > newOptions.count()) {
1115 m_d->executeCmd(DCsetoption, m_boolOptions.first(), 0);
1116 m_boolOptions.remove(m_boolOptions.begin());
1120 void KDebugger::handleLocals(const char* output)
1122 // retrieve old list of local variables
1123 QStrList oldVars;
1124 m_localVariables.exprList(oldVars);
1127 * Get local variables.
1129 QList<VarTree> newVars;
1130 parseLocals(output, newVars);
1133 * Clear any old VarTree item pointers, so that later we don't access
1134 * dangling pointers.
1136 m_localVariables.clearPendingUpdates();
1138 // reduce flicker
1139 bool autoU = m_localVariables.autoUpdate();
1140 m_localVariables.setAutoUpdate(false);
1141 bool repaintNeeded = false;
1144 * Match old variables against new ones.
1146 for (const char* n = oldVars.first(); n != 0; n = oldVars.next()) {
1147 // lookup this variable in the list of new variables
1148 VarTree* v = newVars.first();
1149 while (v != 0 && strcmp(v->getText(), n) != 0) {
1150 v = newVars.next();
1152 if (v == 0) {
1153 // old variable not in the new variables
1154 TRACE(QString("old var deleted: ") + n);
1155 v = m_localVariables.topLevelExprByName(n);
1156 removeExpr(&m_localVariables, v);
1157 if (v != 0) repaintNeeded = true;
1158 } else {
1159 // variable in both old and new lists: update
1160 TRACE(QString("update var: ") + n);
1161 m_localVariables.updateExpr(newVars.current());
1162 // remove the new variable from the list
1163 newVars.remove();
1164 delete v;
1165 repaintNeeded = true;
1168 // insert all remaining new variables
1169 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1170 TRACE("new var: " + v->getText());
1171 m_localVariables.insertExpr(v);
1172 repaintNeeded = true;
1175 // repaint
1176 m_localVariables.setAutoUpdate(autoU);
1177 if (repaintNeeded && autoU && m_localVariables.isVisible())
1178 m_localVariables.repaint();
1181 void KDebugger::parseLocals(const char* output, QList<VarTree>& newVars)
1183 QList<VarTree> vars;
1184 m_d->parseLocals(output, vars);
1186 QString origName; /* used in renaming variables */
1187 while (vars.count() > 0)
1189 VarTree* variable = vars.take(0);
1190 // get some types
1191 variable->inferTypesOfChildren(*m_typeTable);
1193 * When gdb prints local variables, those from the innermost block
1194 * come first. We run through the list of already parsed variables
1195 * to find duplicates (ie. variables that hide local variables from
1196 * a surrounding block). We keep the name of the inner variable, but
1197 * rename those from the outer block so that, when the value is
1198 * updated in the window, the value of the variable that is
1199 * _visible_ changes the color!
1201 int block = 0;
1202 origName = variable->getText();
1203 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1204 if (variable->getText() == v->getText()) {
1205 // we found a duplicate, change name
1206 block++;
1207 QString newName = origName + " (" + QString().setNum(block) + ")";
1208 variable->setText(newName);
1211 newVars.append(variable);
1215 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1217 ASSERT(cmd->m_expr != 0);
1219 VarTree* variable = parseExpr(output, true);
1220 if (variable == 0)
1221 return false;
1223 // set expression "name"
1224 variable->setText(cmd->m_expr->getText());
1226 if (cmd->m_expr->m_varKind == VarTree::VKpointer) {
1228 * We must insert a dummy parent, because otherwise variable's value
1229 * would overwrite cmd->m_expr's value.
1231 VarTree* dummyParent = new VarTree(variable->getText(), VarTree::NKplain);
1232 dummyParent->m_varKind = VarTree::VKdummy;
1233 // the name of the parsed variable is the address of the pointer
1234 QString addr = "*" + cmd->m_expr->m_value;
1235 variable->setText(addr);
1236 variable->m_nameKind = VarTree::NKaddress;
1238 dummyParent->appendChild(variable);
1239 dummyParent->setDeleteChildren(true);
1240 // expand the first level for convenience
1241 variable->setExpanded(true);
1242 TRACE("update ptr: " + cmd->m_expr->getText());
1243 cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent);
1244 delete dummyParent;
1245 } else {
1246 TRACE("update expr: " + cmd->m_expr->getText());
1247 cmd->m_exprWnd->updateExpr(cmd->m_expr, variable);
1248 delete variable;
1251 evalExpressions(); /* enqueue dereferenced pointers */
1253 return true;
1256 VarTree* KDebugger::parseExpr(const char* output, bool wantErrorValue)
1258 VarTree* variable;
1260 // check for error conditions
1261 bool goodValue = m_d->parsePrintExpr(output, wantErrorValue, variable);
1263 if (variable != 0 && goodValue)
1265 // get some types
1266 variable->inferTypesOfChildren(*m_typeTable);
1268 return variable;
1271 // parse the output of bt
1272 void KDebugger::handleBacktrace(const char* output)
1274 // reduce flicker
1275 m_btWindow.setAutoUpdate(false);
1277 m_btWindow.clear();
1279 QList<StackFrame> stack;
1280 m_d->parseBackTrace(output, stack);
1282 if (stack.count() > 0) {
1283 StackFrame* frm = stack.take(0);
1284 // first frame must set PC
1285 // note: frm->lineNo is zero-based
1286 emit updatePC(frm->fileName, frm->lineNo, frm->address, frm->frameNo);
1288 do {
1289 QString func;
1290 if (frm->var != 0)
1291 func = frm->var->getText();
1292 else
1293 func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1294 m_btWindow.insertItem(func);
1295 TRACE("frame " + func + " (" + frm->fileName + ":" +
1296 QString().setNum(frm->lineNo+1) + ")");
1297 delete frm;
1299 while ((frm = stack.take()) != 0);
1302 m_btWindow.setAutoUpdate(true);
1303 m_btWindow.repaint();
1306 void KDebugger::gotoFrame(int frame)
1308 m_d->executeCmd(DCframe, frame);
1311 void KDebugger::handleFrameChange(const char* output)
1313 QString fileName;
1314 int frameNo;
1315 int lineNo;
1316 DbgAddr address;
1317 if (m_d->parseFrameChange(output, frameNo, fileName, lineNo, address)) {
1318 /* lineNo can be negative here if we can't find a file name */
1319 emit updatePC(fileName, lineNo, address, frameNo);
1320 } else {
1321 emit updatePC(fileName, -1, address, frameNo);
1325 void KDebugger::evalExpressions()
1327 // evaluate expressions in the following order:
1328 // watch expressions
1329 // pointers in local variables
1330 // pointers in watch expressions
1331 // types in local variables
1332 // types in watch expressions
1333 // pointers in 'this'
1334 // types in 'this'
1336 VarTree* exprItem = m_watchEvalExpr.first();
1337 if (exprItem != 0) {
1338 m_watchEvalExpr.remove();
1339 QString expr = exprItem->computeExpr();
1340 TRACE("watch expr: " + expr);
1341 CmdQueueItem* cmd = m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverride);
1342 // remember which expr this was
1343 cmd->m_expr = exprItem;
1344 cmd->m_exprWnd = &m_watchVariables;
1345 } else {
1346 ExprWnd* wnd;
1347 VarTree* exprItem;
1348 #define POINTER(widget) \
1349 wnd = &widget; \
1350 exprItem = widget.nextUpdatePtr(); \
1351 if (exprItem != 0) goto pointer
1352 #define STRUCT(widget) \
1353 wnd = &widget; \
1354 exprItem = widget.nextUpdateStruct(); \
1355 if (exprItem != 0) goto ustruct
1356 #define TYPE(widget) \
1357 wnd = &widget; \
1358 exprItem = widget.nextUpdateType(); \
1359 if (exprItem != 0) goto type
1360 repeat:
1361 POINTER(m_localVariables);
1362 POINTER(m_watchVariables);
1363 STRUCT(m_localVariables);
1364 STRUCT(m_watchVariables);
1365 TYPE(m_localVariables);
1366 TYPE(m_watchVariables);
1367 #undef POINTER
1368 #undef STRUCT
1369 #undef TYPE
1370 return;
1372 pointer:
1373 // we have an expression to send
1374 dereferencePointer(wnd, exprItem, false);
1375 return;
1377 ustruct:
1378 // paranoia
1379 if (exprItem->m_type == 0 || exprItem->m_type == TypeInfo::unknownType())
1380 goto repeat;
1381 evalInitialStructExpression(exprItem, wnd, false);
1382 return;
1384 type:
1386 * Sometimes a VarTree gets registered twice for a type update. So
1387 * it may happen that it has already been updated. Hence, we ignore
1388 * it here and go on to the next task.
1390 if (exprItem->m_type != 0)
1391 goto repeat;
1392 determineType(wnd, exprItem);
1396 void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem,
1397 bool immediate)
1399 ASSERT(exprItem->m_varKind == VarTree::VKpointer);
1401 QString expr = exprItem->computeExpr();
1402 TRACE("dereferencing pointer: " + expr);
1403 QString queueExpr = "*(" + expr + ")";
1404 CmdQueueItem* cmd;
1405 if (immediate) {
1406 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverrideMoreEqual);
1407 } else {
1408 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverride);
1410 // remember which expr this was
1411 cmd->m_expr = exprItem;
1412 cmd->m_exprWnd = wnd;
1415 void KDebugger::determineType(ExprWnd* wnd, VarTree* exprItem)
1417 ASSERT(exprItem->m_varKind == VarTree::VKstruct);
1419 QString expr = exprItem->computeExpr();
1420 TRACE("get type of: " + expr);
1421 CmdQueueItem* cmd;
1422 cmd = m_d->queueCmd(DCfindType, expr, DebuggerDriver::QMoverride);
1424 // remember which expr this was
1425 cmd->m_expr = exprItem;
1426 cmd->m_exprWnd = wnd;
1429 void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output)
1431 QString type;
1432 if (m_d->parseFindType(output, type))
1434 ASSERT(cmd != 0 && cmd->m_expr != 0);
1436 TypeInfo* info = m_typeTable->lookup(type);
1438 if (info == 0) {
1440 * We've asked gdb for the type of the expression in
1441 * cmd->m_expr, but it returned a name we don't know. The base
1442 * class (and member) types have been checked already (at the
1443 * time when we parsed that particular expression). Now it's
1444 * time to derive the type from the base classes as a last
1445 * resort.
1447 info = cmd->m_expr->inferTypeFromBaseClass();
1448 // if we found a type through this method, register an alias
1449 if (info != 0) {
1450 TRACE("infered alias: " + type);
1451 m_typeTable->registerAlias(type, info);
1454 if (info == 0) {
1455 TRACE("unknown type");
1456 cmd->m_expr->m_type = TypeInfo::unknownType();
1457 } else {
1458 cmd->m_expr->m_type = info;
1459 /* since this node has a new type, we get its value immediately */
1460 evalInitialStructExpression(cmd->m_expr, cmd->m_exprWnd, false);
1461 return;
1465 evalExpressions(); /* queue more of them */
1468 void KDebugger::handlePrintStruct(CmdQueueItem* cmd, const char* output)
1470 VarTree* var = cmd->m_expr;
1471 ASSERT(var != 0);
1472 ASSERT(var->m_varKind == VarTree::VKstruct);
1474 VarTree* partExpr;
1475 if (cmd->m_cmd != DCprintQStringStruct) {
1476 partExpr = parseExpr(output, false);
1477 } else {
1478 partExpr = m_d->parseQCharArray(output, false, m_typeTable->qCharIsShort());
1480 bool errorValue =
1481 partExpr == 0 ||
1482 /* we only allow simple values at the moment */
1483 partExpr->childCount() != 0;
1485 QString partValue;
1486 if (errorValue)
1488 partValue = "?""?""?"; // 2 question marks in a row would be a trigraph
1489 } else {
1490 partValue = partExpr->m_value;
1492 delete partExpr;
1493 partExpr = 0;
1496 * Updating a struct value works like this: var->m_partialValue holds
1497 * the value that we have gathered so far (it's been initialized with
1498 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1499 * we append the printed result followed by the next
1500 * var->m_type->m_displayString to var->m_partialValue.
1502 * If the expression we just evaluated was a guard expression, and it
1503 * resulted in an error, we must not evaluate the real expression, but
1504 * go on to the next index. (We must still add the question marks to
1505 * the value).
1507 * Next, if this was the length expression, we still have not seen the
1508 * real expression, but the length of a QString.
1510 ASSERT(var->m_exprIndex >= 0 && var->m_exprIndex <= typeInfoMaxExpr);
1512 if (errorValue || !var->m_exprIndexUseGuard)
1514 // add current partValue (which might be the question marks)
1515 var->m_partialValue += partValue;
1516 var->m_exprIndex++; /* next part */
1517 var->m_exprIndexUseGuard = true;
1518 var->m_partialValue += var->m_type->m_displayString[var->m_exprIndex];
1520 else
1522 // this was a guard expression that succeeded
1523 // go for the real expression
1524 var->m_exprIndexUseGuard = false;
1527 /* go for more sub-expressions if needed */
1528 if (var->m_exprIndex < var->m_type->m_numExprs) {
1529 /* queue a new print command with quite high priority */
1530 evalStructExpression(var, cmd->m_exprWnd, true);
1531 return;
1534 cmd->m_exprWnd->updateStructValue(var);
1536 evalExpressions(); /* enqueue dereferenced pointers */
1539 /* queues the first printStruct command for a struct */
1540 void KDebugger::evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1542 var->m_exprIndex = 0;
1543 var->m_exprIndexUseGuard = true;
1544 var->m_partialValue = var->m_type->m_displayString[0];
1545 evalStructExpression(var, wnd, immediate);
1548 /* queues a printStruct command; var must have been initialized correctly */
1549 void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1551 QString base = var->computeExpr();
1552 QString exprFmt;
1553 if (var->m_exprIndexUseGuard) {
1554 exprFmt = var->m_type->m_guardStrings[var->m_exprIndex];
1555 if (exprFmt.isEmpty()) {
1556 // no guard, omit it and go to expression
1557 var->m_exprIndexUseGuard = false;
1560 if (!var->m_exprIndexUseGuard) {
1561 exprFmt = var->m_type->m_exprStrings[var->m_exprIndex];
1564 SIZED_QString(expr, exprFmt.length() + base.length() + 10);
1565 expr.sprintf(exprFmt, base.data());
1567 DbgCommand dbgCmd = DCprintStruct;
1568 // check if this is a QString::Data
1569 if (strncmp(expr, "/QString::Data ", 15) == 0)
1571 if (m_typeTable->parseQt2QStrings())
1573 expr = expr.mid(15, expr.length()); /* strip off /QString::Data */
1574 dbgCmd = DCprintQStringStruct;
1575 } else {
1577 * This should not happen: the type libraries should be set up
1578 * in a way that this can't happen. If this happens
1579 * nevertheless it means that, eg., kdecore was loaded but qt2
1580 * was not (only qt2 enables the QString feature).
1582 // TODO: remove this "print"; queue the next printStruct instead
1583 expr = "*0";
1585 } else {
1586 expr = expr;
1588 TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1589 CmdQueueItem* cmd = m_d->queueCmd(dbgCmd, expr,
1590 immediate ? DebuggerDriver::QMoverrideMoreEqual
1591 : DebuggerDriver::QMnormal);
1593 // remember which expression this was
1594 cmd->m_expr = var;
1595 cmd->m_exprWnd = wnd;
1598 /* removes expression from window */
1599 void KDebugger::removeExpr(ExprWnd* wnd, VarTree* var)
1601 if (var == 0)
1602 return;
1604 // must remove any references to var from command queues
1605 m_d->dequeueCmdByVar(var);
1607 wnd->removeExpr(var);
1610 void KDebugger::handleSharedLibs(const char* output)
1612 // delete all known libraries
1613 m_sharedLibs.clear();
1615 // parse the table of shared libraries
1616 m_d->parseSharedLibs(output, m_sharedLibs);
1617 m_sharedLibsListed = true;
1619 // get type libraries
1620 m_typeTable->loadLibTypes(m_sharedLibs);
1623 CmdQueueItem* KDebugger::loadCoreFile()
1625 return m_d->queueCmd(DCcorefile, m_corefile, DebuggerDriver::QMoverride);
1628 void KDebugger::slotLocalsExpanding(KTreeViewItem* item, bool& allow)
1630 exprExpandingHelper(&m_localVariables, item, allow);
1633 void KDebugger::slotWatchExpanding(KTreeViewItem* item, bool& allow)
1635 exprExpandingHelper(&m_watchVariables, item, allow);
1638 void KDebugger::exprExpandingHelper(ExprWnd* wnd, KTreeViewItem* item, bool&)
1640 VarTree* exprItem = static_cast<VarTree*>(item);
1641 if (exprItem->m_varKind != VarTree::VKpointer) {
1642 return;
1644 dereferencePointer(wnd, exprItem, true);
1647 // add the expression in the edit field to the watch expressions
1648 void KDebugger::addWatch(const QString& t)
1650 QString expr = t.stripWhiteSpace();
1651 if (expr.isEmpty())
1652 return;
1653 VarTree* exprItem = new VarTree(expr, VarTree::NKplain);
1654 m_watchVariables.insertExpr(exprItem);
1656 // if we are boring ourselves, send down the command
1657 if (m_programActive) {
1658 m_watchEvalExpr.append(exprItem);
1659 if (m_d->isIdle()) {
1660 evalExpressions();
1665 // delete a toplevel watch expression
1666 void KDebugger::slotDeleteWatch()
1668 // delete only allowed while debugger is idle; or else we might delete
1669 // the very expression the debugger is currently working on...
1670 if (!m_d->isIdle())
1671 return;
1673 int index = m_watchVariables.currentItem();
1674 if (index < 0)
1675 return;
1677 VarTree* item = static_cast<VarTree*>(m_watchVariables.itemAt(index));
1678 if (!item->isToplevelExpr())
1679 return;
1681 // remove the variable from the list to evaluate
1682 if (m_watchEvalExpr.findRef(item) >= 0) {
1683 m_watchEvalExpr.remove();
1685 removeExpr(&m_watchVariables, item);
1686 // item is invalid at this point!
1689 void KDebugger::startAnimation(bool fast)
1691 int interval = fast ? 50 : 150;
1692 if (!m_animationTimer.isActive()) {
1693 m_animationTimer.start(interval);
1694 } else if (m_animationInterval != interval) {
1695 m_animationTimer.changeInterval(interval);
1697 m_animationInterval = interval;
1700 void KDebugger::stopAnimation()
1702 if (m_animationTimer.isActive()) {
1703 m_animationTimer.stop();
1704 m_animationInterval = 0;
1708 void KDebugger::slotUpdateAnimation()
1710 if (isIdle()) {
1711 stopAnimation();
1712 } else {
1714 * Slow animation while program is stopped (i.e. while variables
1715 * are displayed)
1717 bool slow = isReady() && m_programActive && !m_programRunning;
1718 startAnimation(!slow);
1722 void KDebugger::handleRegisters(const char* output)
1724 QList<RegisterInfo> regs;
1725 m_d->parseRegisters(output, regs);
1727 emit registersChanged(regs);
1729 // delete them all
1730 regs.setAutoDelete(true);
1734 * The output of the DCbreak* commands has more accurate information about
1735 * the file and the line number.
1737 void KDebugger::newBreakpoint(const char* output)
1739 int id;
1740 QString file;
1741 int lineNo;
1742 if (!m_d->parseBreakpoint(output, id, file, lineNo))
1743 return;
1745 // see if it is new
1746 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1747 if (m_brkpts[i]->id == id) {
1748 // not new; update
1749 m_brkpts[i]->fileName = file;
1750 m_brkpts[i]->lineNo = lineNo;
1751 return;
1754 // yes, new
1755 Breakpoint* bp = new Breakpoint;
1756 bp->id = id;
1757 bp->temporary = false;
1758 bp->enabled = true;
1759 bp->hitCount = 0;
1760 bp->ignoreCount = 0;
1761 bp->fileName = file;
1762 bp->lineNo = lineNo;
1763 int n = m_brkpts.size();
1764 m_brkpts.resize(n+1);
1765 m_brkpts[n] = bp;
1768 void KDebugger::updateBreakList(const char* output)
1770 // get the new list
1771 QList<Breakpoint> brks;
1772 brks.setAutoDelete(false);
1773 m_d->parseBreakList(output, brks);
1775 // merge new information into existing breakpoints
1777 QArray<Breakpoint*> oldbrks = m_brkpts;
1779 // move parsed breakpoints into m_brkpts
1780 m_brkpts.detach();
1781 m_brkpts.resize(brks.count());
1782 int n = 0;
1783 for (Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
1785 m_brkpts[n++] = bp;
1788 // go through all old breakpoints
1789 for (int i = oldbrks.size()-1; i >= 0; i--) {
1790 // is this one still alive?
1791 for (int j = m_brkpts.size()-1; j >= 0; j--)
1793 if (m_brkpts[j]->id == oldbrks[i]->id) {
1794 // yes, it is
1795 // keep accurate location
1796 m_brkpts[j]->fileName = oldbrks[i]->fileName;
1797 m_brkpts[j]->lineNo = oldbrks[i]->lineNo;
1798 break;
1803 // delete old breakpoints
1804 for (int i = oldbrks.size()-1; i >= 0; i--) {
1805 delete oldbrks[i];
1808 emit breakpointsChanged();
1811 // look if there is at least one temporary breakpoint
1812 // or a watchpoint
1813 bool KDebugger::stopMayChangeBreakList() const
1815 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1816 Breakpoint* bp = m_brkpts[i];
1817 if (bp->temporary || bp->type == Breakpoint::watchpoint)
1818 return true;
1820 return false;
1823 Breakpoint* KDebugger::breakpointByFilePos(QString file, int lineNo,
1824 const DbgAddr& address)
1826 // look for exact file name match
1827 int i;
1828 for (i = m_brkpts.size()-1; i >= 0; i--) {
1829 if (m_brkpts[i]->lineNo == lineNo &&
1830 m_brkpts[i]->fileName == file &&
1831 (address.isEmpty() || m_brkpts[i]->address == address))
1833 return m_brkpts[i];
1836 // not found, so try basename
1837 // strip off directory part of file name
1838 int offset = file.findRev("/");
1839 file.remove(0, offset+1);
1841 for (i = m_brkpts.size()-1; i >= 0; i--) {
1842 // get base name of breakpoint's file
1843 QString basename = m_brkpts[i]->fileName;
1844 int offset = basename.findRev("/");
1845 if (offset >= 0) {
1846 basename.remove(0, offset+1);
1849 if (m_brkpts[i]->lineNo == lineNo &&
1850 basename == file &&
1851 (address.isEmpty() || m_brkpts[i]->address == address))
1853 return m_brkpts[i];
1857 // not found
1858 return 0;
1861 void KDebugger::slotValuePopup(const QString& expr)
1863 // search the local variables for a match
1864 VarTree* v = m_localVariables.topLevelExprByName(expr);
1865 if (v == 0) {
1866 // not found, check watch expressions
1867 v = m_watchVariables.topLevelExprByName(expr);
1868 if (v == 0) {
1869 // nothing found; do nothing
1870 return;
1874 // construct the tip
1875 QString tip = v->getText() + " = ";
1876 if (!v->m_value.isEmpty())
1878 tip += v->m_value;
1880 else
1882 // no value: we use some hint
1883 switch (v->m_varKind) {
1884 case VarTree::VKstruct:
1885 tip += "{...}";
1886 break;
1887 case VarTree::VKarray:
1888 tip += "[...]";
1889 break;
1890 default:
1891 tip += "?""?""?"; // 2 question marks in a row would be a trigraph
1892 break;
1895 emit valuePopup(tip);
1898 void KDebugger::slotDisassemble(const QString& fileName, int lineNo)
1900 CmdQueueItem* cmd = m_d->queueCmd(DCinfoline, fileName, lineNo,
1901 DebuggerDriver::QMoverrideMoreEqual);
1902 cmd->m_fileName = fileName;
1903 cmd->m_lineNo = lineNo;
1906 void KDebugger::handleInfoLine(CmdQueueItem* cmd, const char* output)
1908 QString addrFrom, addrTo;
1909 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
1910 // got the address range, now get the real code
1911 CmdQueueItem* c = m_d->queueCmd(DCdisassemble, addrFrom, addrTo,
1912 DebuggerDriver::QMoverrideMoreEqual);
1913 c->m_fileName = cmd->m_fileName;
1914 c->m_lineNo = cmd->m_lineNo;
1915 } else {
1916 // no code
1917 QList<DisassembledCode> empty;
1918 emit disassembled(cmd->m_fileName, cmd->m_lineNo, empty);
1922 void KDebugger::handleDisassemble(CmdQueueItem* cmd, const char* output)
1924 QList<DisassembledCode> code;
1925 code.setAutoDelete(true);
1926 m_d->parseDisassemble(output, code);
1927 emit disassembled(cmd->m_fileName, cmd->m_lineNo, code);
1930 void KDebugger::handleThreadList(const char* output)
1932 QList<ThreadInfo> threads;
1933 threads.setAutoDelete(true);
1934 m_d->parseThreadList(output, threads);
1935 emit threadsChanged(threads);
1938 void KDebugger::setThread(int id)
1940 m_d->queueCmd(DCthread, id, DebuggerDriver::QMoverrideMoreEqual);
1943 void KDebugger::setMemoryExpression(const QString& memexpr)
1945 m_memoryExpression = memexpr;
1947 // queue the new expression
1948 if (!m_memoryExpression.isEmpty() &&
1949 isProgramActive() &&
1950 !isProgramRunning())
1952 queueMemoryDump(true);
1956 void KDebugger::queueMemoryDump(bool immediate)
1958 m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat,
1959 immediate ? DebuggerDriver::QMoverrideMoreEqual :
1960 DebuggerDriver::QMoverride);
1963 void KDebugger::handleMemoryDump(const char* output)
1965 QList<MemoryDump> memdump;
1966 memdump.setAutoDelete(true);
1967 QString msg = m_d->parseMemoryDump(output, memdump);
1968 emit memoryDumpChanged(msg, memdump);
1972 #include "debugger.moc"