Converted the array of breakpoints to a QPtrVector.
[kdbg.git] / kdbg / debugger.cpp
blobe61125d29833cecbba339f042a5097c1364db5c5
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);
51 m_brkpts.setAutoDelete(true);
53 connect(&m_localVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
54 SLOT(slotLocalsExpanding(KTreeViewItem*,bool&)));
55 connect(&m_watchVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
56 SLOT(slotWatchExpanding(KTreeViewItem*,bool&)));
58 connect(&m_btWindow, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
60 // animation
61 connect(&m_animationTimer, SIGNAL(timeout()), SIGNAL(animationTimeout()));
62 // special update of animation
63 connect(this, SIGNAL(updateUI()), SLOT(slotUpdateAnimation()));
65 emit updateUI();
68 KDebugger::~KDebugger()
70 if (m_programConfig != 0) {
71 saveProgramSettings();
72 m_programConfig->sync();
73 delete m_programConfig;
76 delete m_typeTable;
80 void KDebugger::saveSettings(KConfig* /*config*/)
84 void KDebugger::restoreSettings(KConfig* /*config*/)
89 //////////////////////////////////////////////////////////////////////
90 // external interface
92 const char GeneralGroup[] = "General";
93 const char DebuggerCmdStr[] = "DebuggerCmdStr";
94 const char TTYLevelEntry[] = "TTYLevel";
95 const char KDebugger::DriverNameEntry[] = "DriverName";
97 bool KDebugger::debugProgram(const QString& name,
98 DebuggerDriver* driver)
100 if (m_d != 0 && m_d->isRunning())
102 QApplication::setOverrideCursor(waitCursor);
104 stopDriver();
106 QApplication::restoreOverrideCursor();
108 if (m_d->isRunning() || m_haveExecutable) {
109 /* timed out! We can't really do anything useful now */
110 TRACE("timed out while waiting for gdb to die!");
111 return false;
113 delete m_d;
114 m_d = 0;
117 // wire up the driver
118 connect(driver, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
119 this, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)));
120 connect(driver, SIGNAL(processExited(KProcess*)), SLOT(gdbExited(KProcess*)));
121 connect(driver, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
122 SLOT(parse(CmdQueueItem*,const char*)));
123 connect(driver, SIGNAL(wroteStdin(KProcess*)), SIGNAL(updateUI()));
124 connect(driver, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
125 connect(driver, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
126 connect(driver, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
128 // create the program settings object
129 openProgramConfig(name);
131 // get debugger command from per-program settings
132 if (m_programConfig != 0) {
133 m_programConfig->setGroup(GeneralGroup);
134 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
135 // get terminal emulation level
136 m_ttyLevel = TTYLevel(m_programConfig->readNumEntry(TTYLevelEntry, ttyFull));
138 // the rest is read in later in the handler of DCexecutable
140 m_d = driver;
142 if (!startDriver()) {
143 TRACE("startDriver failed");
144 m_d = 0;
145 return false;
148 TRACE("before file cmd");
149 m_d->executeCmd(DCexecutable, name);
150 m_executable = name;
152 // set remote target
153 if (!m_remoteDevice.isEmpty()) {
154 m_d->executeCmd(DCtargetremote, m_remoteDevice);
155 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
156 m_d->queueCmd(DCframe, 0, DebuggerDriver::QMnormal);
157 m_programActive = true;
158 m_haveExecutable = true;
161 // create a type table
162 m_typeTable = new ProgramTypeTable;
163 m_sharedLibsListed = false;
165 emit updateUI();
167 return true;
170 void KDebugger::shutdown()
172 // shut down debugger driver
173 if (m_d != 0 && m_d->isRunning())
175 stopDriver();
179 void KDebugger::useCoreFile(QString corefile, bool batch)
181 m_corefile = corefile;
182 if (!batch) {
183 CmdQueueItem* cmd = loadCoreFile();
184 cmd->m_byUser = true;
188 void KDebugger::programRun()
190 if (!isReady())
191 return;
193 // when program is active, but not a core file, continue
194 // otherwise run the program
195 if (m_programActive && m_corefile.isEmpty()) {
196 // gdb command: continue
197 m_d->executeCmd(DCcont, true);
198 } else {
199 // gdb command: run
200 m_d->executeCmd(DCrun, true);
201 m_corefile = QString();
202 m_programActive = true;
204 m_programRunning = true;
207 void KDebugger::attachProgram(const QString& pid)
209 if (!isReady())
210 return;
212 m_attachedPid = pid;
213 TRACE("Attaching to " + m_attachedPid);
214 m_d->executeCmd(DCattach, m_attachedPid);
215 m_programActive = true;
216 m_programRunning = true;
219 void KDebugger::programRunAgain()
221 if (canSingleStep()) {
222 m_d->executeCmd(DCrun, true);
223 m_corefile = QString();
224 m_programRunning = true;
228 void KDebugger::programStep()
230 if (canSingleStep()) {
231 m_d->executeCmd(DCstep, true);
232 m_programRunning = true;
236 void KDebugger::programNext()
238 if (canSingleStep()) {
239 m_d->executeCmd(DCnext, true);
240 m_programRunning = true;
244 void KDebugger::programStepi()
246 if (canSingleStep()) {
247 m_d->executeCmd(DCstepi, true);
248 m_programRunning = true;
252 void KDebugger::programNexti()
254 if (canSingleStep()) {
255 m_d->executeCmd(DCnexti, true);
256 m_programRunning = true;
260 void KDebugger::programFinish()
262 if (canSingleStep()) {
263 m_d->executeCmd(DCfinish, true);
264 m_programRunning = true;
268 void KDebugger::programKill()
270 if (haveExecutable() && isProgramActive()) {
271 if (m_programRunning) {
272 m_d->interruptInferior();
274 // this is an emergency command; flush queues
275 m_d->flushCommands(true);
276 m_d->executeCmd(DCkill, true);
280 bool KDebugger::runUntil(const QString& fileName, int lineNo)
282 if (isReady() && m_programActive && !m_programRunning) {
283 // strip off directory part of file name
284 QString file = fileName;
285 int offset = file.findRev("/");
286 if (offset >= 0) {
287 file.remove(0, offset+1);
289 m_d->executeCmd(DCuntil, file, lineNo, true);
290 m_programRunning = true;
291 return true;
292 } else {
293 return false;
297 void KDebugger::programBreak()
299 if (m_haveExecutable && m_programRunning) {
300 m_d->interruptInferior();
304 void KDebugger::programArgs(QWidget* parent)
306 if (m_haveExecutable) {
307 QStringList allOptions = m_d->boolOptionList();
308 PgmArgs dlg(parent, m_executable, m_envVars, allOptions);
309 dlg.setArgs(m_programArgs);
310 dlg.setWd(m_programWD);
311 dlg.setOptions(m_boolOptions);
312 if (dlg.exec()) {
313 updateProgEnvironment(dlg.args(), dlg.wd(),
314 dlg.envVars(), dlg.options());
319 void KDebugger::programSettings(QWidget* parent)
321 if (!m_haveExecutable)
322 return;
324 ProgramSettings dlg(parent, m_executable);
326 dlg.m_chooseDriver.setDebuggerCmd(m_debuggerCmd);
327 dlg.m_output.setTTYLevel(m_ttyLevel);
329 if (dlg.exec() == QDialog::Accepted)
331 m_debuggerCmd = dlg.m_chooseDriver.debuggerCmd();
332 m_ttyLevel = TTYLevel(dlg.m_output.ttyLevel());
336 bool KDebugger::setBreakpoint(QString file, int lineNo,
337 const DbgAddr& address, bool temporary)
339 if (!isReady()) {
340 return false;
343 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
344 if (bp == 0)
347 * No such breakpoint, so set a new one. If we have an address, we
348 * set the breakpoint exactly there. Otherwise we use the file name
349 * plus line no.
351 if (address.isEmpty())
353 // strip off directory part of file name
354 int offset = file.findRev("/");
355 if (offset >= 0) {
356 file.remove(0, offset+1);
358 m_d->executeCmd(temporary ? DCtbreakline : DCbreakline,
359 file, lineNo);
361 else
363 m_d->executeCmd(temporary ? DCtbreakaddr : DCbreakaddr,
364 address.asString());
367 else
370 * If the breakpoint is disabled, enable it; if it's enabled,
371 * delete that breakpoint.
373 if (bp->enabled) {
374 m_d->executeCmd(DCdelete, bp->id);
375 } else {
376 m_d->executeCmd(DCenable, bp->id);
379 return true;
382 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo,
383 const DbgAddr& address)
385 if (!isReady()) {
386 return false;
389 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
390 if (bp == 0)
391 return true;
393 // toggle enabled/disabled state
394 if (bp->enabled) {
395 m_d->executeCmd(DCdisable, bp->id);
396 } else {
397 m_d->executeCmd(DCenable, bp->id);
399 return true;
402 bool KDebugger::canSingleStep()
404 return isReady() && m_programActive && !m_programRunning;
407 bool KDebugger::canChangeBreakpoints()
409 return isReady() && !m_programRunning;
412 bool KDebugger::isReady() const
414 return m_haveExecutable &&
415 m_d != 0 && m_d->canExecuteImmediately();
418 bool KDebugger::isIdle() const
420 return m_d == 0 || m_d->isIdle();
424 //////////////////////////////////////////////////////////
425 // debugger driver
427 bool KDebugger::startDriver()
429 emit debuggerStarting(); /* must set m_inferiorTerminal */
432 * If the per-program command string is empty, use the global setting
433 * (which might also be empty, in which case the driver uses its
434 * default).
436 m_explicitKill = false;
437 if (!m_d->startup(m_debuggerCmd)) {
438 return false;
442 * If we have an output terminal, we use it. Otherwise we will run the
443 * program with input and output redirected to /dev/null. Other
444 * redirections are also necessary depending on the tty emulation
445 * level.
447 int redirect = RDNstdin|RDNstdout|RDNstderr; /* redirect everything */
448 if (!m_inferiorTerminal.isEmpty()) {
449 switch (m_ttyLevel) {
450 default:
451 case ttyNone:
452 // redirect everything
453 break;
454 case ttySimpleOutputOnly:
455 redirect = RDNstdin;
456 break;
457 case ttyFull:
458 redirect = 0;
459 break;
462 m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
464 return true;
467 void KDebugger::stopDriver()
469 m_explicitKill = true;
471 if (m_attachedPid.isEmpty()) {
472 m_d->terminate();
473 } else {
474 m_d->detachAndTerminate();
478 * We MUST wait until the slot gdbExited() has been called. But to
479 * avoid a deadlock, we wait only for some certain maximum time. Should
480 * this timeout be reached, the only reasonable thing one could do then
481 * is exiting kdbg.
483 kapp->processEvents(1000); /* ideally, this will already shut it down */
484 int maxTime = 20; /* about 20 seconds */
485 while (m_haveExecutable && maxTime > 0) {
486 // give gdb time to die (and send a SIGCLD)
487 ::sleep(1);
488 --maxTime;
489 kapp->processEvents(1000);
493 void KDebugger::gdbExited(KProcess*)
496 * Save settings, but only if gdb has already processed "info line
497 * main", otherwise we would save an empty config file, because it
498 * isn't read in until then!
500 if (m_programConfig != 0) {
501 if (m_haveExecutable) {
502 saveProgramSettings();
503 m_programConfig->sync();
505 delete m_programConfig;
506 m_programConfig = 0;
509 // erase types
510 delete m_typeTable;
511 m_typeTable = 0;
513 if (m_explicitKill) {
514 TRACE(m_d->driverName() + " exited normally");
515 } else {
516 QString msg = i18n("%1 exited unexpectedly.\n"
517 "Restart the session (e.g. with File|Executable).");
518 KMessageBox::error(parentWidget(), msg.arg(m_d->driverName()));
521 // reset state
522 m_haveExecutable = false;
523 m_executable = "";
524 m_programActive = false;
525 m_programRunning = false;
526 m_explicitKill = false;
527 m_debuggerCmd = QString(); /* use global setting at next start! */
528 m_attachedPid = QString(); /* we are no longer attached to a process */
529 m_ttyLevel = ttyFull;
530 m_brkpts.clear();
532 // stop gear wheel and erase PC
533 stopAnimation();
534 emit updatePC(QString(), -1, DbgAddr(), 0);
537 QString KDebugger::getConfigForExe(const QString& name)
539 QFileInfo fi(name);
540 QString pgmConfigFile = fi.dirPath(true);
541 if (!pgmConfigFile.isEmpty()) {
542 pgmConfigFile += '/';
544 pgmConfigFile += ".kdbgrc." + fi.fileName();
545 TRACE("program config file = " + pgmConfigFile);
546 return pgmConfigFile;
549 void KDebugger::openProgramConfig(const QString& name)
551 ASSERT(m_programConfig == 0);
553 QString pgmConfigFile = getConfigForExe(name);
554 // check whether we can write to the file
555 QFile file(pgmConfigFile);
556 bool readonly = true;
557 bool openit = true;
558 if (file.open(IO_ReadWrite)) { /* don't truncate! */
559 readonly = false;
560 // the file exists now
561 } else if (!file.open(IO_ReadOnly)) {
562 /* file does not exist and cannot be created: don't use it */
563 openit = false;
565 if (openit) {
566 m_programConfig = new KSimpleConfig(pgmConfigFile, readonly);
570 const char EnvironmentGroup[] = "Environment";
571 const char WatchGroup[] = "Watches";
572 const char FileVersion[] = "FileVersion";
573 const char ProgramArgs[] = "ProgramArgs";
574 const char WorkingDirectory[] = "WorkingDirectory";
575 const char OptionsSelected[] = "OptionsSelected";
576 const char Variable[] = "Var%d";
577 const char Value[] = "Value%d";
578 const char ExprFmt[] = "Expr%d";
580 void KDebugger::saveProgramSettings()
582 ASSERT(m_programConfig != 0);
583 m_programConfig->setGroup(GeneralGroup);
584 m_programConfig->writeEntry(FileVersion, 1);
585 m_programConfig->writeEntry(ProgramArgs, m_programArgs);
586 m_programConfig->writeEntry(WorkingDirectory, m_programWD);
587 m_programConfig->writeEntry(OptionsSelected, m_boolOptions);
588 m_programConfig->writeEntry(DebuggerCmdStr, m_debuggerCmd);
589 m_programConfig->writeEntry(TTYLevelEntry, int(m_ttyLevel));
590 QString driverName;
591 if (m_d != 0)
592 driverName = m_d->driverName();
593 m_programConfig->writeEntry(DriverNameEntry, driverName);
595 // write environment variables
596 m_programConfig->deleteGroup(EnvironmentGroup);
597 m_programConfig->setGroup(EnvironmentGroup);
598 QDictIterator<EnvVar> it = m_envVars;
599 EnvVar* var;
600 QString varName;
601 QString varValue;
602 for (int i = 0; (var = it) != 0; ++it, ++i) {
603 varName.sprintf(Variable, i);
604 varValue.sprintf(Value, i);
605 m_programConfig->writeEntry(varName, it.currentKey());
606 m_programConfig->writeEntry(varValue, var->value);
609 saveBreakpoints(m_programConfig);
611 // watch expressions
612 // first get rid of whatever was in this group
613 m_programConfig->deleteGroup(WatchGroup);
614 // then start a new group
615 m_programConfig->setGroup(WatchGroup);
616 KTreeViewItem* item = m_watchVariables.itemAt(0);
617 int watchNum = 0;
618 for (; item != 0; item = item->getSibling(), ++watchNum) {
619 varName.sprintf(ExprFmt, watchNum);
620 m_programConfig->writeEntry(varName, item->getText());
623 // give others a chance
624 emit saveProgramSpecific(m_programConfig);
627 void KDebugger::restoreProgramSettings()
629 ASSERT(m_programConfig != 0);
630 m_programConfig->setGroup(GeneralGroup);
632 * We ignore file version for now we will use it in the future to
633 * distinguish different versions of this configuration file.
635 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
636 // m_ttyLevel has been read in already
637 QString pgmArgs = m_programConfig->readEntry(ProgramArgs);
638 QString pgmWd = m_programConfig->readEntry(WorkingDirectory);
639 QStringList boolOptions = m_programConfig->readListEntry(OptionsSelected);
640 m_boolOptions = QStringList();
642 // read environment variables
643 m_programConfig->setGroup(EnvironmentGroup);
644 m_envVars.clear();
645 QDict<EnvVar> pgmVars;
646 EnvVar* var;
647 QString varName;
648 QString varValue;
649 for (int i = 0;; ++i) {
650 varName.sprintf(Variable, i);
651 varValue.sprintf(Value, i);
652 if (!m_programConfig->hasKey(varName)) {
653 /* entry not present, assume that we've hit them all */
654 break;
656 QString name = m_programConfig->readEntry(varName);
657 if (name.isEmpty()) {
658 // skip empty names
659 continue;
661 var = new EnvVar;
662 var->value = m_programConfig->readEntry(varValue);
663 var->status = EnvVar::EVnew;
664 pgmVars.insert(name, var);
667 updateProgEnvironment(pgmArgs, pgmWd, pgmVars, boolOptions);
669 restoreBreakpoints(m_programConfig);
671 // watch expressions
672 m_programConfig->setGroup(WatchGroup);
673 m_watchVariables.clear();
674 for (int i = 0;; ++i) {
675 varName.sprintf(ExprFmt, i);
676 if (!m_programConfig->hasKey(varName)) {
677 /* entry not present, assume that we've hit them all */
678 break;
680 QString expr = m_programConfig->readEntry(varName);
681 if (expr.isEmpty()) {
682 // skip empty expressions
683 continue;
685 addWatch(expr);
688 // give others a chance
689 emit restoreProgramSpecific(m_programConfig);
693 * Breakpoints are saved one per group.
695 const char BPGroup[] = "Breakpoint %d";
696 const char File[] = "File";
697 const char Line[] = "Line";
698 const char Address[] = "Address";
699 const char Temporary[] = "Temporary";
700 const char Enabled[] = "Enabled";
701 const char Condition[] = "Condition";
703 void KDebugger::saveBreakpoints(KSimpleConfig* config)
705 QString groupName;
706 int i = 0;
707 for (uint j = 0; j < m_brkpts.count(); j++) {
708 Breakpoint* bp = m_brkpts[j];
709 if (bp->type == Breakpoint::watchpoint)
710 continue; /* don't save watchpoints */
711 groupName.sprintf(BPGroup, i++);
712 config->setGroup(groupName);
713 if (!bp->fileName.isEmpty()) {
714 config->writeEntry(File, bp->fileName);
715 config->writeEntry(Line, bp->lineNo);
717 * Addresses are hardly correct across sessions, so we remove
718 * it since we have a file name and line number.
720 config->deleteEntry(Address, false);
721 } else {
722 config->writeEntry(Address, bp->address.asString());
723 /* remove remmants */
724 config->deleteEntry(File, false);
725 config->deleteEntry(Line, false);
727 config->writeEntry(Temporary, bp->temporary);
728 config->writeEntry(Enabled, bp->enabled);
729 if (bp->condition.isEmpty())
730 config->deleteEntry(Condition, false);
731 else
732 config->writeEntry(Condition, bp->condition);
733 // we do not save the ignore count
735 // delete remaining groups
736 // we recognize that a group is present if there is an Enabled entry
737 for (;; i++) {
738 groupName.sprintf(BPGroup, i);
739 config->setGroup(groupName);
740 if (!config->hasKey(Enabled)) {
741 /* group not present, assume that we've hit them all */
742 break;
744 config->deleteGroup(groupName);
748 void KDebugger::restoreBreakpoints(KSimpleConfig* config)
750 QString groupName;
752 * We recognize the end of the list if there is no Enabled entry
753 * present.
755 for (int i = 0;; i++) {
756 groupName.sprintf(BPGroup, i);
757 config->setGroup(groupName);
758 if (!config->hasKey(Enabled)) {
759 /* group not present, assume that we've hit them all */
760 break;
762 Breakpoint* bp = new Breakpoint;
763 bp->fileName = config->readEntry(File);
764 bp->lineNo = config->readNumEntry(Line, -1);
765 bp->address = config->readEntry(Address);
766 if ((bp->fileName.isEmpty() || bp->lineNo < 0) && bp->address.isEmpty()) {
767 delete bp;
768 continue;
770 bp->enabled = config->readBoolEntry(Enabled, true);
771 bp->temporary = config->readBoolEntry(Temporary, false);
772 bp->condition = config->readEntry(Condition);
773 bp->hitCount = 0;
774 bp->ignoreCount = 0;
775 bp->id = 0;
778 * Add the breakpoint.
780 CmdQueueItem* cmd;
781 if (!bp->fileName.isEmpty()) {
782 cmd = m_d->executeCmd(bp->temporary ? DCtbreakline : DCbreakline,
783 bp->fileName, bp->lineNo);
784 } else {
785 cmd = m_d->executeCmd(bp->temporary ? DCtbreakaddr : DCbreakaddr,
786 bp->address.asString());
788 // the new breakpoint is disabled or conditionalized later
789 // in newBreakpoint() using this reference:
790 cmd->m_brkpt = bp;
792 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
796 // parse output of command cmd
797 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
799 ASSERT(cmd != 0); /* queue mustn't be empty */
801 TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
803 switch (cmd->m_cmd) {
804 case DCtargetremote:
805 // the output (if any) is uninteresting
806 case DCsetargs:
807 case DCtty:
808 // there is no output
809 case DCsetenv:
810 case DCunsetenv:
811 case DCsetoption:
812 /* if value is empty, we see output, but we don't care */
813 break;
814 case DCcd:
815 /* display gdb's message in the status bar */
816 m_d->parseChangeWD(output, m_statusMessage);
817 emit updateStatusMessage();
818 break;
819 case DCinitialize:
820 break;
821 case DCexecutable:
822 if (m_d->parseChangeExecutable(output, m_statusMessage))
824 // success; restore breakpoints etc.
825 if (m_programConfig != 0) {
826 restoreProgramSettings();
828 // load file containing main() or core file
829 if (m_corefile.isEmpty()) {
830 if (m_remoteDevice.isEmpty())
831 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
832 } else {
833 // load core file
834 loadCoreFile();
836 if (!m_statusMessage.isEmpty())
837 emit updateStatusMessage();
838 } else {
839 QString msg = m_d->driverName() + ": " + m_statusMessage;
840 KMessageBox::sorry(parentWidget(), msg);
841 m_executable = "";
842 m_corefile = ""; /* don't process core file */
843 m_haveExecutable = false;
845 break;
846 case DCcorefile:
847 // in any event we have an executable at this point
848 m_haveExecutable = true;
849 if (m_d->parseCoreFile(output)) {
850 // loading a core is like stopping at a breakpoint
851 m_programActive = true;
852 handleRunCommands(output);
853 // do not reset m_corefile
854 } else {
855 // report error
856 QString msg = m_d->driverName() + ": " + QString(output);
857 KMessageBox::sorry(parentWidget(), msg);
859 // if core file was loaded from command line, revert to info line main
860 if (!cmd->m_byUser) {
861 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
863 m_corefile = QString(); /* core file not available any more */
865 break;
866 case DCinfolinemain:
867 // ignore the output, marked file info follows
868 m_haveExecutable = true;
869 break;
870 case DCinfolocals:
871 // parse local variables
872 if (output[0] != '\0') {
873 handleLocals(output);
875 break;
876 case DCinforegisters:
877 handleRegisters(output);
878 break;
879 case DCexamine:
880 handleMemoryDump(output);
881 break;
882 case DCinfoline:
883 handleInfoLine(cmd, output);
884 break;
885 case DCdisassemble:
886 handleDisassemble(cmd, output);
887 break;
888 case DCframe:
889 handleFrameChange(output);
890 updateAllExprs();
891 break;
892 case DCbt:
893 handleBacktrace(output);
894 updateAllExprs();
895 break;
896 case DCprint:
897 handlePrint(cmd, output);
898 break;
899 case DCattach:
900 case DCrun:
901 case DCcont:
902 case DCstep:
903 case DCstepi:
904 case DCnext:
905 case DCnexti:
906 case DCfinish:
907 case DCuntil:
908 case DCthread:
909 handleRunCommands(output);
910 break;
911 case DCkill:
912 m_programRunning = m_programActive = false;
913 // erase PC
914 emit updatePC(QString(), -1, DbgAddr(), 0);
915 break;
916 case DCbreaktext:
917 case DCbreakline:
918 case DCtbreakline:
919 case DCbreakaddr:
920 case DCtbreakaddr:
921 case DCwatchpoint:
922 newBreakpoint(cmd, output);
923 // fall through
924 case DCdelete:
925 case DCenable:
926 case DCdisable:
927 // these commands need immediate response
928 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverrideMoreEqual);
929 break;
930 case DCinfobreak:
931 // note: this handler must not enqueue a command, since
932 // DCinfobreak is used at various different places.
933 updateBreakList(output);
934 emit lineItemsChanged();
935 break;
936 case DCfindType:
937 handleFindType(cmd, output);
938 break;
939 case DCprintStruct:
940 case DCprintQStringStruct:
941 handlePrintStruct(cmd, output);
942 break;
943 case DCinfosharedlib:
944 handleSharedLibs(output);
945 break;
946 case DCcondition:
947 case DCignore:
948 // we are not interested in the output
949 break;
950 case DCinfothreads:
951 handleThreadList(output);
952 break;
953 case DCsetpc:
954 handleSetPC(output);
955 break;
959 void KDebugger::backgroundUpdate()
962 * If there are still expressions that need to be updated, then do so.
964 if (m_programActive)
965 evalExpressions();
968 void KDebugger::handleRunCommands(const char* output)
970 uint flags = m_d->parseProgramStopped(output, m_statusMessage);
971 emit updateStatusMessage();
973 m_programActive = flags & DebuggerDriver::SFprogramActive;
975 // refresh files if necessary
976 if (flags & DebuggerDriver::SFrefreshSource) {
977 TRACE("re-reading files");
978 emit executableUpdated();
982 * If we stopped at a breakpoint, we must update the breakpoint list
983 * because the hit count changes. Also, if the breakpoint was temporary
984 * it would go away now.
986 if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
987 stopMayChangeBreakList())
989 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
993 * If we haven't listed the shared libraries yet, do so. We must do
994 * this before we emit any commands that list variables, since the type
995 * libraries depend on the shared libraries.
997 if (!m_sharedLibsListed) {
998 // must be a high-priority command!
999 m_d->executeCmd(DCinfosharedlib);
1002 // get the backtrace if the program is running
1003 if (m_programActive) {
1004 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
1005 } else {
1006 // program finished: erase PC
1007 emit updatePC(QString(), -1, DbgAddr(), 0);
1008 // dequeue any commands in the queues
1009 m_d->flushCommands();
1012 /* Update threads list */
1013 if (flags & DebuggerDriver::SFrefreshThreads) {
1014 m_d->queueCmd(DCinfothreads, DebuggerDriver::QMoverride);
1017 m_programRunning = false;
1018 emit programStopped();
1021 void KDebugger::slotInferiorRunning()
1023 m_programRunning = true;
1026 void KDebugger::updateAllExprs()
1028 if (!m_programActive)
1029 return;
1031 // retrieve local variables
1032 m_d->queueCmd(DCinfolocals, DebuggerDriver::QMoverride);
1034 // retrieve registers
1035 m_d->queueCmd(DCinforegisters, DebuggerDriver::QMoverride);
1037 // get new memory dump
1038 if (!m_memoryExpression.isEmpty()) {
1039 queueMemoryDump(false);
1042 // update watch expressions
1043 KTreeViewItem* item = m_watchVariables.itemAt(0);
1044 for (; item != 0; item = item->getSibling()) {
1045 m_watchEvalExpr.append(static_cast<VarTree*>(item));
1049 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
1050 const QDict<EnvVar>& newVars,
1051 const QStringList& newOptions)
1053 m_programArgs = args;
1054 m_d->executeCmd(DCsetargs, m_programArgs);
1055 TRACE("new pgm args: " + m_programArgs + "\n");
1057 m_programWD = wd.stripWhiteSpace();
1058 if (!m_programWD.isEmpty()) {
1059 m_d->executeCmd(DCcd, m_programWD);
1060 TRACE("new wd: " + m_programWD + "\n");
1063 // update environment variables
1064 QDictIterator<EnvVar> it = newVars;
1065 EnvVar* val;
1066 for (; (val = it) != 0; ++it) {
1067 QString var = it.currentKey();
1068 switch (val->status) {
1069 case EnvVar::EVnew:
1070 m_envVars.insert(var, val);
1071 // fall thru
1072 case EnvVar::EVdirty:
1073 // the value must be in our list
1074 ASSERT(m_envVars[var] == val);
1075 // update value
1076 m_d->executeCmd(DCsetenv, var, val->value);
1077 break;
1078 case EnvVar::EVdeleted:
1079 // must be in our list
1080 ASSERT(m_envVars[var] == val);
1081 // delete value
1082 m_d->executeCmd(DCunsetenv, var);
1083 m_envVars.remove(var);
1084 break;
1085 default:
1086 ASSERT(false);
1087 case EnvVar::EVclean:
1088 // variable not changed
1089 break;
1093 // update options
1094 QStringList::ConstIterator oi;
1095 for (oi = newOptions.begin(); oi != newOptions.end(); ++oi)
1097 if (m_boolOptions.findIndex(*oi) < 0) {
1098 // the options is currently not set, so set it
1099 m_d->executeCmd(DCsetoption, *oi, 1);
1100 } else {
1101 // option is set, no action required, but move it to the end
1102 m_boolOptions.remove(*oi);
1104 m_boolOptions.append(*oi);
1107 * Now all options that should be set are at the end of m_boolOptions.
1108 * If some options need to be unset, they are at the front of the list.
1109 * Here we unset and remove them.
1111 while (m_boolOptions.count() > newOptions.count()) {
1112 m_d->executeCmd(DCsetoption, m_boolOptions.first(), 0);
1113 m_boolOptions.remove(m_boolOptions.begin());
1117 void KDebugger::handleLocals(const char* output)
1119 // retrieve old list of local variables
1120 QStrList oldVars;
1121 m_localVariables.exprList(oldVars);
1124 * Get local variables.
1126 QList<VarTree> newVars;
1127 parseLocals(output, newVars);
1130 * Clear any old VarTree item pointers, so that later we don't access
1131 * dangling pointers.
1133 m_localVariables.clearPendingUpdates();
1135 // reduce flicker
1136 bool autoU = m_localVariables.autoUpdate();
1137 m_localVariables.setAutoUpdate(false);
1138 bool repaintNeeded = false;
1141 * Match old variables against new ones.
1143 for (const char* n = oldVars.first(); n != 0; n = oldVars.next()) {
1144 // lookup this variable in the list of new variables
1145 VarTree* v = newVars.first();
1146 while (v != 0 && strcmp(v->getText(), n) != 0) {
1147 v = newVars.next();
1149 if (v == 0) {
1150 // old variable not in the new variables
1151 TRACE(QString("old var deleted: ") + n);
1152 v = m_localVariables.topLevelExprByName(n);
1153 removeExpr(&m_localVariables, v);
1154 if (v != 0) repaintNeeded = true;
1155 } else {
1156 // variable in both old and new lists: update
1157 TRACE(QString("update var: ") + n);
1158 m_localVariables.updateExpr(newVars.current());
1159 // remove the new variable from the list
1160 newVars.remove();
1161 delete v;
1162 repaintNeeded = true;
1165 // insert all remaining new variables
1166 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1167 TRACE("new var: " + v->getText());
1168 m_localVariables.insertExpr(v);
1169 repaintNeeded = true;
1172 // repaint
1173 m_localVariables.setAutoUpdate(autoU);
1174 if (repaintNeeded && autoU && m_localVariables.isVisible())
1175 m_localVariables.repaint();
1178 void KDebugger::parseLocals(const char* output, QList<VarTree>& newVars)
1180 QList<VarTree> vars;
1181 m_d->parseLocals(output, vars);
1183 QString origName; /* used in renaming variables */
1184 while (vars.count() > 0)
1186 VarTree* variable = vars.take(0);
1187 // get some types
1188 variable->inferTypesOfChildren(*m_typeTable);
1190 * When gdb prints local variables, those from the innermost block
1191 * come first. We run through the list of already parsed variables
1192 * to find duplicates (ie. variables that hide local variables from
1193 * a surrounding block). We keep the name of the inner variable, but
1194 * rename those from the outer block so that, when the value is
1195 * updated in the window, the value of the variable that is
1196 * _visible_ changes the color!
1198 int block = 0;
1199 origName = variable->getText();
1200 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1201 if (variable->getText() == v->getText()) {
1202 // we found a duplicate, change name
1203 block++;
1204 QString newName = origName + " (" + QString().setNum(block) + ")";
1205 variable->setText(newName);
1208 newVars.append(variable);
1212 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1214 ASSERT(cmd->m_expr != 0);
1216 VarTree* variable = parseExpr(output, true);
1217 if (variable == 0)
1218 return false;
1220 // set expression "name"
1221 variable->setText(cmd->m_expr->getText());
1223 if (cmd->m_expr->m_varKind == VarTree::VKpointer) {
1225 * We must insert a dummy parent, because otherwise variable's value
1226 * would overwrite cmd->m_expr's value.
1228 VarTree* dummyParent = new VarTree(variable->getText(), VarTree::NKplain);
1229 dummyParent->m_varKind = VarTree::VKdummy;
1230 // the name of the parsed variable is the address of the pointer
1231 QString addr = "*" + cmd->m_expr->m_value;
1232 variable->setText(addr);
1233 variable->m_nameKind = VarTree::NKaddress;
1235 dummyParent->appendChild(variable);
1236 dummyParent->setDeleteChildren(true);
1237 // expand the first level for convenience
1238 variable->setExpanded(true);
1239 TRACE("update ptr: " + cmd->m_expr->getText());
1240 cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent);
1241 delete dummyParent;
1242 } else {
1243 TRACE("update expr: " + cmd->m_expr->getText());
1244 cmd->m_exprWnd->updateExpr(cmd->m_expr, variable);
1245 delete variable;
1248 evalExpressions(); /* enqueue dereferenced pointers */
1250 return true;
1253 VarTree* KDebugger::parseExpr(const char* output, bool wantErrorValue)
1255 VarTree* variable;
1257 // check for error conditions
1258 bool goodValue = m_d->parsePrintExpr(output, wantErrorValue, variable);
1260 if (variable != 0 && goodValue)
1262 // get some types
1263 variable->inferTypesOfChildren(*m_typeTable);
1265 return variable;
1268 // parse the output of bt
1269 void KDebugger::handleBacktrace(const char* output)
1271 // reduce flicker
1272 m_btWindow.setAutoUpdate(false);
1274 m_btWindow.clear();
1276 QList<StackFrame> stack;
1277 m_d->parseBackTrace(output, stack);
1279 if (stack.count() > 0) {
1280 StackFrame* frm = stack.take(0);
1281 // first frame must set PC
1282 // note: frm->lineNo is zero-based
1283 emit updatePC(frm->fileName, frm->lineNo, frm->address, frm->frameNo);
1285 do {
1286 QString func;
1287 if (frm->var != 0)
1288 func = frm->var->getText();
1289 else
1290 func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1291 m_btWindow.insertItem(func);
1292 TRACE("frame " + func + " (" + frm->fileName + ":" +
1293 QString().setNum(frm->lineNo+1) + ")");
1294 delete frm;
1296 while ((frm = stack.take()) != 0);
1299 m_btWindow.setAutoUpdate(true);
1300 m_btWindow.repaint();
1303 void KDebugger::gotoFrame(int frame)
1305 m_d->executeCmd(DCframe, frame);
1308 void KDebugger::handleFrameChange(const char* output)
1310 QString fileName;
1311 int frameNo;
1312 int lineNo;
1313 DbgAddr address;
1314 if (m_d->parseFrameChange(output, frameNo, fileName, lineNo, address)) {
1315 /* lineNo can be negative here if we can't find a file name */
1316 emit updatePC(fileName, lineNo, address, frameNo);
1317 } else {
1318 emit updatePC(fileName, -1, address, frameNo);
1322 void KDebugger::evalExpressions()
1324 // evaluate expressions in the following order:
1325 // watch expressions
1326 // pointers in local variables
1327 // pointers in watch expressions
1328 // types in local variables
1329 // types in watch expressions
1330 // pointers in 'this'
1331 // types in 'this'
1333 VarTree* exprItem = m_watchEvalExpr.first();
1334 if (exprItem != 0) {
1335 m_watchEvalExpr.remove();
1336 QString expr = exprItem->computeExpr();
1337 TRACE("watch expr: " + expr);
1338 CmdQueueItem* cmd = m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverride);
1339 // remember which expr this was
1340 cmd->m_expr = exprItem;
1341 cmd->m_exprWnd = &m_watchVariables;
1342 } else {
1343 ExprWnd* wnd;
1344 VarTree* exprItem;
1345 #define POINTER(widget) \
1346 wnd = &widget; \
1347 exprItem = widget.nextUpdatePtr(); \
1348 if (exprItem != 0) goto pointer
1349 #define STRUCT(widget) \
1350 wnd = &widget; \
1351 exprItem = widget.nextUpdateStruct(); \
1352 if (exprItem != 0) goto ustruct
1353 #define TYPE(widget) \
1354 wnd = &widget; \
1355 exprItem = widget.nextUpdateType(); \
1356 if (exprItem != 0) goto type
1357 repeat:
1358 POINTER(m_localVariables);
1359 POINTER(m_watchVariables);
1360 STRUCT(m_localVariables);
1361 STRUCT(m_watchVariables);
1362 TYPE(m_localVariables);
1363 TYPE(m_watchVariables);
1364 #undef POINTER
1365 #undef STRUCT
1366 #undef TYPE
1367 return;
1369 pointer:
1370 // we have an expression to send
1371 dereferencePointer(wnd, exprItem, false);
1372 return;
1374 ustruct:
1375 // paranoia
1376 if (exprItem->m_type == 0 || exprItem->m_type == TypeInfo::unknownType())
1377 goto repeat;
1378 evalInitialStructExpression(exprItem, wnd, false);
1379 return;
1381 type:
1383 * Sometimes a VarTree gets registered twice for a type update. So
1384 * it may happen that it has already been updated. Hence, we ignore
1385 * it here and go on to the next task.
1387 if (exprItem->m_type != 0)
1388 goto repeat;
1389 determineType(wnd, exprItem);
1393 void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem,
1394 bool immediate)
1396 ASSERT(exprItem->m_varKind == VarTree::VKpointer);
1398 QString expr = exprItem->computeExpr();
1399 TRACE("dereferencing pointer: " + expr);
1400 QString queueExpr = "*(" + expr + ")";
1401 CmdQueueItem* cmd;
1402 if (immediate) {
1403 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverrideMoreEqual);
1404 } else {
1405 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverride);
1407 // remember which expr this was
1408 cmd->m_expr = exprItem;
1409 cmd->m_exprWnd = wnd;
1412 void KDebugger::determineType(ExprWnd* wnd, VarTree* exprItem)
1414 ASSERT(exprItem->m_varKind == VarTree::VKstruct);
1416 QString expr = exprItem->computeExpr();
1417 TRACE("get type of: " + expr);
1418 CmdQueueItem* cmd;
1419 cmd = m_d->queueCmd(DCfindType, expr, DebuggerDriver::QMoverride);
1421 // remember which expr this was
1422 cmd->m_expr = exprItem;
1423 cmd->m_exprWnd = wnd;
1426 void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output)
1428 QString type;
1429 if (m_d->parseFindType(output, type))
1431 ASSERT(cmd != 0 && cmd->m_expr != 0);
1433 TypeInfo* info = m_typeTable->lookup(type);
1435 if (info == 0) {
1437 * We've asked gdb for the type of the expression in
1438 * cmd->m_expr, but it returned a name we don't know. The base
1439 * class (and member) types have been checked already (at the
1440 * time when we parsed that particular expression). Now it's
1441 * time to derive the type from the base classes as a last
1442 * resort.
1444 info = cmd->m_expr->inferTypeFromBaseClass();
1445 // if we found a type through this method, register an alias
1446 if (info != 0) {
1447 TRACE("infered alias: " + type);
1448 m_typeTable->registerAlias(type, info);
1451 if (info == 0) {
1452 TRACE("unknown type");
1453 cmd->m_expr->m_type = TypeInfo::unknownType();
1454 } else {
1455 cmd->m_expr->m_type = info;
1456 /* since this node has a new type, we get its value immediately */
1457 evalInitialStructExpression(cmd->m_expr, cmd->m_exprWnd, false);
1458 return;
1462 evalExpressions(); /* queue more of them */
1465 void KDebugger::handlePrintStruct(CmdQueueItem* cmd, const char* output)
1467 VarTree* var = cmd->m_expr;
1468 ASSERT(var != 0);
1469 ASSERT(var->m_varKind == VarTree::VKstruct);
1471 VarTree* partExpr;
1472 if (cmd->m_cmd != DCprintQStringStruct) {
1473 partExpr = parseExpr(output, false);
1474 } else {
1475 partExpr = m_d->parseQCharArray(output, false, m_typeTable->qCharIsShort());
1477 bool errorValue =
1478 partExpr == 0 ||
1479 /* we only allow simple values at the moment */
1480 partExpr->childCount() != 0;
1482 QString partValue;
1483 if (errorValue)
1485 partValue = "?""?""?"; // 2 question marks in a row would be a trigraph
1486 } else {
1487 partValue = partExpr->m_value;
1489 delete partExpr;
1490 partExpr = 0;
1493 * Updating a struct value works like this: var->m_partialValue holds
1494 * the value that we have gathered so far (it's been initialized with
1495 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1496 * we append the printed result followed by the next
1497 * var->m_type->m_displayString to var->m_partialValue.
1499 * If the expression we just evaluated was a guard expression, and it
1500 * resulted in an error, we must not evaluate the real expression, but
1501 * go on to the next index. (We must still add the question marks to
1502 * the value).
1504 * Next, if this was the length expression, we still have not seen the
1505 * real expression, but the length of a QString.
1507 ASSERT(var->m_exprIndex >= 0 && var->m_exprIndex <= typeInfoMaxExpr);
1509 if (errorValue || !var->m_exprIndexUseGuard)
1511 // add current partValue (which might be the question marks)
1512 var->m_partialValue += partValue;
1513 var->m_exprIndex++; /* next part */
1514 var->m_exprIndexUseGuard = true;
1515 var->m_partialValue += var->m_type->m_displayString[var->m_exprIndex];
1517 else
1519 // this was a guard expression that succeeded
1520 // go for the real expression
1521 var->m_exprIndexUseGuard = false;
1524 /* go for more sub-expressions if needed */
1525 if (var->m_exprIndex < var->m_type->m_numExprs) {
1526 /* queue a new print command with quite high priority */
1527 evalStructExpression(var, cmd->m_exprWnd, true);
1528 return;
1531 cmd->m_exprWnd->updateStructValue(var);
1533 evalExpressions(); /* enqueue dereferenced pointers */
1536 /* queues the first printStruct command for a struct */
1537 void KDebugger::evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1539 var->m_exprIndex = 0;
1540 var->m_exprIndexUseGuard = true;
1541 var->m_partialValue = var->m_type->m_displayString[0];
1542 evalStructExpression(var, wnd, immediate);
1545 /* queues a printStruct command; var must have been initialized correctly */
1546 void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1548 QString base = var->computeExpr();
1549 QString exprFmt;
1550 if (var->m_exprIndexUseGuard) {
1551 exprFmt = var->m_type->m_guardStrings[var->m_exprIndex];
1552 if (exprFmt.isEmpty()) {
1553 // no guard, omit it and go to expression
1554 var->m_exprIndexUseGuard = false;
1557 if (!var->m_exprIndexUseGuard) {
1558 exprFmt = var->m_type->m_exprStrings[var->m_exprIndex];
1561 SIZED_QString(expr, exprFmt.length() + base.length() + 10);
1562 expr.sprintf(exprFmt, base.data());
1564 DbgCommand dbgCmd = DCprintStruct;
1565 // check if this is a QString::Data
1566 if (strncmp(expr, "/QString::Data ", 15) == 0)
1568 if (m_typeTable->parseQt2QStrings())
1570 expr = expr.mid(15, expr.length()); /* strip off /QString::Data */
1571 dbgCmd = DCprintQStringStruct;
1572 } else {
1574 * This should not happen: the type libraries should be set up
1575 * in a way that this can't happen. If this happens
1576 * nevertheless it means that, eg., kdecore was loaded but qt2
1577 * was not (only qt2 enables the QString feature).
1579 // TODO: remove this "print"; queue the next printStruct instead
1580 expr = "*0";
1582 } else {
1583 expr = expr;
1585 TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1586 CmdQueueItem* cmd = m_d->queueCmd(dbgCmd, expr,
1587 immediate ? DebuggerDriver::QMoverrideMoreEqual
1588 : DebuggerDriver::QMnormal);
1590 // remember which expression this was
1591 cmd->m_expr = var;
1592 cmd->m_exprWnd = wnd;
1595 /* removes expression from window */
1596 void KDebugger::removeExpr(ExprWnd* wnd, VarTree* var)
1598 if (var == 0)
1599 return;
1601 // must remove any references to var from command queues
1602 m_d->dequeueCmdByVar(var);
1604 wnd->removeExpr(var);
1607 void KDebugger::handleSharedLibs(const char* output)
1609 // delete all known libraries
1610 m_sharedLibs.clear();
1612 // parse the table of shared libraries
1613 m_d->parseSharedLibs(output, m_sharedLibs);
1614 m_sharedLibsListed = true;
1616 // get type libraries
1617 m_typeTable->loadLibTypes(m_sharedLibs);
1620 CmdQueueItem* KDebugger::loadCoreFile()
1622 return m_d->queueCmd(DCcorefile, m_corefile, DebuggerDriver::QMoverride);
1625 void KDebugger::slotLocalsExpanding(KTreeViewItem* item, bool& allow)
1627 exprExpandingHelper(&m_localVariables, item, allow);
1630 void KDebugger::slotWatchExpanding(KTreeViewItem* item, bool& allow)
1632 exprExpandingHelper(&m_watchVariables, item, allow);
1635 void KDebugger::exprExpandingHelper(ExprWnd* wnd, KTreeViewItem* item, bool&)
1637 VarTree* exprItem = static_cast<VarTree*>(item);
1638 if (exprItem->m_varKind != VarTree::VKpointer) {
1639 return;
1641 dereferencePointer(wnd, exprItem, true);
1644 // add the expression in the edit field to the watch expressions
1645 void KDebugger::addWatch(const QString& t)
1647 QString expr = t.stripWhiteSpace();
1648 if (expr.isEmpty())
1649 return;
1650 VarTree* exprItem = new VarTree(expr, VarTree::NKplain);
1651 m_watchVariables.insertExpr(exprItem);
1653 // if we are boring ourselves, send down the command
1654 if (m_programActive) {
1655 m_watchEvalExpr.append(exprItem);
1656 if (m_d->isIdle()) {
1657 evalExpressions();
1662 // delete a toplevel watch expression
1663 void KDebugger::slotDeleteWatch()
1665 // delete only allowed while debugger is idle; or else we might delete
1666 // the very expression the debugger is currently working on...
1667 if (!m_d->isIdle())
1668 return;
1670 int index = m_watchVariables.currentItem();
1671 if (index < 0)
1672 return;
1674 VarTree* item = static_cast<VarTree*>(m_watchVariables.itemAt(index));
1675 if (!item->isToplevelExpr())
1676 return;
1678 // remove the variable from the list to evaluate
1679 if (m_watchEvalExpr.findRef(item) >= 0) {
1680 m_watchEvalExpr.remove();
1682 removeExpr(&m_watchVariables, item);
1683 // item is invalid at this point!
1686 void KDebugger::startAnimation(bool fast)
1688 int interval = fast ? 50 : 150;
1689 if (!m_animationTimer.isActive()) {
1690 m_animationTimer.start(interval);
1691 } else if (m_animationInterval != interval) {
1692 m_animationTimer.changeInterval(interval);
1694 m_animationInterval = interval;
1697 void KDebugger::stopAnimation()
1699 if (m_animationTimer.isActive()) {
1700 m_animationTimer.stop();
1701 m_animationInterval = 0;
1705 void KDebugger::slotUpdateAnimation()
1707 if (isIdle()) {
1708 stopAnimation();
1709 } else {
1711 * Slow animation while program is stopped (i.e. while variables
1712 * are displayed)
1714 bool slow = isReady() && m_programActive && !m_programRunning;
1715 startAnimation(!slow);
1719 void KDebugger::handleRegisters(const char* output)
1721 QList<RegisterInfo> regs;
1722 m_d->parseRegisters(output, regs);
1724 emit registersChanged(regs);
1726 // delete them all
1727 regs.setAutoDelete(true);
1731 * The output of the DCbreak* commands has more accurate information about
1732 * the file and the line number.
1734 void KDebugger::newBreakpoint(CmdQueueItem* cmd, const char* output)
1736 int id;
1737 QString file;
1738 int lineNo;
1739 QString address;
1740 if (!m_d->parseBreakpoint(output, id, file, lineNo, address))
1742 delete cmd->m_brkpt;
1743 return;
1746 // is this a breakpoint restored from the settings?
1747 if (cmd->m_brkpt != 0)
1749 // yes, add it
1750 cmd->m_brkpt->id = id;
1752 int n = m_brkpts.count();
1753 m_brkpts.resize(n+1);
1754 m_brkpts.insert(n, cmd->m_brkpt);
1756 // set the remaining properties
1757 if (!cmd->m_brkpt->enabled) {
1758 m_d->executeCmd(DCdisable, id);
1760 if (!cmd->m_brkpt->condition.isEmpty()) {
1761 m_d->executeCmd(DCcondition, cmd->m_brkpt->condition, id);
1765 // see if it is new
1766 for (int i = m_brkpts.count()-1; i >= 0; i--) {
1767 if (m_brkpts[i]->id == id) {
1768 // not new; update
1769 m_brkpts[i]->fileName = file;
1770 m_brkpts[i]->lineNo = lineNo;
1771 if (!address.isEmpty())
1772 m_brkpts[i]->address = address;
1773 return;
1776 // yes, new
1777 Breakpoint* bp = new Breakpoint;
1778 bp->id = id;
1779 bp->temporary = false;
1780 bp->enabled = true;
1781 bp->hitCount = 0;
1782 bp->ignoreCount = 0;
1783 bp->fileName = file;
1784 bp->lineNo = lineNo;
1785 bp->address = address;
1786 int n = m_brkpts.count();
1787 m_brkpts.resize(n+1);
1788 m_brkpts.insert(n, bp);
1791 void KDebugger::updateBreakList(const char* output)
1793 // get the new list
1794 QList<Breakpoint> brks;
1795 brks.setAutoDelete(false);
1796 m_d->parseBreakList(output, brks);
1798 // merge new information into existing breakpoints
1800 // move parsed breakpoints into a QPtrVector
1801 QPtrVector<Breakpoint> newbrks(brks.count());
1802 newbrks.setAutoDelete(false);
1803 int n = 0;
1804 for (Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
1806 newbrks.insert(n++, bp);
1809 // go through all old breakpoints
1810 for (int i = m_brkpts.count()-1; i >= 0; i--) {
1811 // is this one still alive?
1812 for (int j = newbrks.count()-1; j >= 0; j--)
1814 if (newbrks[j]->id == m_brkpts[i]->id) {
1815 // yes, it is
1816 // keep accurate location
1817 newbrks[j]->fileName = m_brkpts[i]->fileName;
1818 newbrks[j]->lineNo = m_brkpts[i]->lineNo;
1819 break;
1823 m_brkpts = newbrks; // old Breakpoint objects are deleted
1825 emit breakpointsChanged();
1828 // look if there is at least one temporary breakpoint
1829 // or a watchpoint
1830 bool KDebugger::stopMayChangeBreakList() const
1832 for (int i = m_brkpts.count()-1; i >= 0; i--) {
1833 Breakpoint* bp = m_brkpts[i];
1834 if (bp->temporary || bp->type == Breakpoint::watchpoint)
1835 return true;
1837 return false;
1840 Breakpoint* KDebugger::breakpointByFilePos(QString file, int lineNo,
1841 const DbgAddr& address)
1843 // look for exact file name match
1844 int i;
1845 for (i = m_brkpts.count()-1; i >= 0; i--) {
1846 if (m_brkpts[i]->lineNo == lineNo &&
1847 m_brkpts[i]->fileName == file &&
1848 (address.isEmpty() || m_brkpts[i]->address == address))
1850 return m_brkpts[i];
1853 // not found, so try basename
1854 // strip off directory part of file name
1855 int offset = file.findRev("/");
1856 file.remove(0, offset+1);
1858 for (i = m_brkpts.count()-1; i >= 0; i--) {
1859 // get base name of breakpoint's file
1860 QString basename = m_brkpts[i]->fileName;
1861 int offset = basename.findRev("/");
1862 if (offset >= 0) {
1863 basename.remove(0, offset+1);
1866 if (m_brkpts[i]->lineNo == lineNo &&
1867 basename == file &&
1868 (address.isEmpty() || m_brkpts[i]->address == address))
1870 return m_brkpts[i];
1874 // not found
1875 return 0;
1878 void KDebugger::slotValuePopup(const QString& expr)
1880 // search the local variables for a match
1881 VarTree* v = m_localVariables.topLevelExprByName(expr);
1882 if (v == 0) {
1883 // not found, check watch expressions
1884 v = m_watchVariables.topLevelExprByName(expr);
1885 if (v == 0) {
1886 // nothing found; do nothing
1887 return;
1891 // construct the tip
1892 QString tip = v->getText() + " = ";
1893 if (!v->m_value.isEmpty())
1895 tip += v->m_value;
1897 else
1899 // no value: we use some hint
1900 switch (v->m_varKind) {
1901 case VarTree::VKstruct:
1902 tip += "{...}";
1903 break;
1904 case VarTree::VKarray:
1905 tip += "[...]";
1906 break;
1907 default:
1908 tip += "?""?""?"; // 2 question marks in a row would be a trigraph
1909 break;
1912 emit valuePopup(tip);
1915 void KDebugger::slotDisassemble(const QString& fileName, int lineNo)
1917 CmdQueueItem* cmd = m_d->queueCmd(DCinfoline, fileName, lineNo,
1918 DebuggerDriver::QMoverrideMoreEqual);
1919 cmd->m_fileName = fileName;
1920 cmd->m_lineNo = lineNo;
1923 void KDebugger::handleInfoLine(CmdQueueItem* cmd, const char* output)
1925 QString addrFrom, addrTo;
1926 if (cmd->m_lineNo >= 0) {
1927 // disassemble
1928 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
1929 // got the address range, now get the real code
1930 CmdQueueItem* c = m_d->queueCmd(DCdisassemble, addrFrom, addrTo,
1931 DebuggerDriver::QMoverrideMoreEqual);
1932 c->m_fileName = cmd->m_fileName;
1933 c->m_lineNo = cmd->m_lineNo;
1934 } else {
1935 // no code
1936 QList<DisassembledCode> empty;
1937 emit disassembled(cmd->m_fileName, cmd->m_lineNo, empty);
1939 } else {
1940 // set program counter
1941 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
1942 // move the program counter to the start address
1943 m_d->executeCmd(DCsetpc, addrFrom);
1948 void KDebugger::handleDisassemble(CmdQueueItem* cmd, const char* output)
1950 QList<DisassembledCode> code;
1951 code.setAutoDelete(true);
1952 m_d->parseDisassemble(output, code);
1953 emit disassembled(cmd->m_fileName, cmd->m_lineNo, code);
1956 void KDebugger::handleThreadList(const char* output)
1958 QList<ThreadInfo> threads;
1959 threads.setAutoDelete(true);
1960 m_d->parseThreadList(output, threads);
1961 emit threadsChanged(threads);
1964 void KDebugger::setThread(int id)
1966 m_d->queueCmd(DCthread, id, DebuggerDriver::QMoverrideMoreEqual);
1969 void KDebugger::setMemoryExpression(const QString& memexpr)
1971 m_memoryExpression = memexpr;
1973 // queue the new expression
1974 if (!m_memoryExpression.isEmpty() &&
1975 isProgramActive() &&
1976 !isProgramRunning())
1978 queueMemoryDump(true);
1982 void KDebugger::queueMemoryDump(bool immediate)
1984 m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat,
1985 immediate ? DebuggerDriver::QMoverrideMoreEqual :
1986 DebuggerDriver::QMoverride);
1989 void KDebugger::handleMemoryDump(const char* output)
1991 QList<MemoryDump> memdump;
1992 memdump.setAutoDelete(true);
1993 QString msg = m_d->parseMemoryDump(output, memdump);
1994 emit memoryDumpChanged(msg, memdump);
1997 void KDebugger::setProgramCounter(const QString& file, int line, const DbgAddr& addr)
1999 if (addr.isEmpty()) {
2000 // find address of the specified line
2001 CmdQueueItem* cmd = m_d->executeCmd(DCinfoline, file, line);
2002 cmd->m_lineNo = -1; /* indicates "Set PC" UI command */
2003 } else {
2004 // move the program counter to that address
2005 m_d->executeCmd(DCsetpc, addr.asString());
2009 void KDebugger::handleSetPC(const char* /*output*/)
2011 // TODO: handle errors
2013 // now go to the top-most frame
2014 // this also modifies the program counter indicator in the UI
2015 gotoFrame(0);
2019 #include "debugger.moc"