3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
13 #include <qfileinfo.h>
16 #include <ksimpleconfig.h>
20 #include <klocale.h> /* i18n */
21 #include <kmessagebox.h>
26 #include <stdlib.h> /* strtol, atoi */
28 #include <unistd.h> /* sleep(3) */
33 KDebugger::KDebugger(QWidget
* parent
,
37 DebuggerDriver
* driver
39 QObject(parent
, "debugger"),
41 m_haveExecutable(false),
42 m_programActive(false),
43 m_programRunning(false),
44 m_sharedLibsListed(false),
48 m_localVariables(*localVars
),
49 m_watchVariables(*watchVars
),
50 m_btWindow(*backtrace
),
51 m_animationTimer(this),
52 m_animationInterval(0)
54 m_envVars
.setAutoDelete(true);
56 connect(&m_localVariables
, SIGNAL(expanding(KTreeViewItem
*,bool&)),
57 SLOT(slotLocalsExpanding(KTreeViewItem
*,bool&)));
58 connect(&m_watchVariables
, SIGNAL(expanding(KTreeViewItem
*,bool&)),
59 SLOT(slotWatchExpanding(KTreeViewItem
*,bool&)));
61 connect(&m_btWindow
, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
63 connect(m_d
, SIGNAL(activateFileLine(const QString
&,int)),
64 this, SIGNAL(activateFileLine(const QString
&,int)));
67 connect(m_d
, SIGNAL(processExited(KProcess
*)), SLOT(gdbExited(KProcess
*)));
68 connect(m_d
, SIGNAL(commandReceived(CmdQueueItem
*,const char*)),
69 SLOT(parse(CmdQueueItem
*,const char*)));
70 // we shouldn't do this, it's very unsafe (different arg lists):
71 connect(m_d
, SIGNAL(receivedStdout(KProcess
*,char*,int)),
73 connect(m_d
, SIGNAL(wroteStdin(KProcess
*)), SIGNAL(updateUI()));
74 connect(m_d
, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
75 connect(m_d
, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
78 connect(&m_animationTimer
, SIGNAL(timeout()), SIGNAL(animationTimeout()));
79 // special update of animation
80 connect(this, SIGNAL(updateUI()), SLOT(slotUpdateAnimation()));
85 KDebugger::~KDebugger()
87 if (m_programConfig
!= 0) {
88 saveProgramSettings();
89 m_programConfig
->sync();
90 delete m_programConfig
;
92 // delete breakpoint objects
93 for (int i
= m_brkpts
.size()-1; i
>= 0; i
--) {
101 void KDebugger::saveSettings(KConfig
* /*config*/)
105 void KDebugger::restoreSettings(KConfig
* /*config*/)
110 //////////////////////////////////////////////////////////////////////
111 // external interface
113 const char GeneralGroup
[] = "General";
114 const char DebuggerCmdStr
[] = "DebuggerCmdStr";
115 const char TTYLevelEntry
[] = "TTYLevel";
117 bool KDebugger::debugProgram(const QString
& name
)
119 if (m_d
->isRunning())
121 QApplication::setOverrideCursor(waitCursor
);
125 * We MUST wait until the slot gdbExited() has been called. But to
126 * avoid a deadlock, we wait only for some certain maximum time.
127 * Should this timeout be reached, the only reasonable thing one
128 * could do then is exiting kdbg.
130 int maxTime
= 20; /* about 20 seconds */
131 while (m_haveExecutable
&& maxTime
> 0) {
132 kapp
->processEvents(1000);
133 // give gdb time to die (and send a SIGCLD)
138 QApplication::restoreOverrideCursor();
140 if (m_d
->isRunning() || m_haveExecutable
) {
141 /* timed out! We can't really do anything useful now */
142 TRACE("timed out while waiting for gdb to die!");
147 // create the program settings object
148 openProgramConfig(name
);
150 // get debugger command from per-program settings
151 if (m_programConfig
!= 0) {
152 m_programConfig
->setGroup(GeneralGroup
);
153 m_debuggerCmd
= m_programConfig
->readEntry(DebuggerCmdStr
);
154 // get terminal emulation level
155 m_ttyLevel
= TTYLevel(m_programConfig
->readNumEntry(TTYLevelEntry
, ttyFull
));
157 // the rest is read in later in the handler of DCexecutable
160 TRACE("startGdb failed");
164 TRACE("before file cmd");
165 m_d
->executeCmd(DCexecutable
, name
);
169 if (!m_remoteDevice
.isEmpty()) {
170 m_d
->executeCmd(DCtargetremote
, m_remoteDevice
);
171 m_d
->queueCmd(DCbt
, DebuggerDriver::QMoverride
);
172 m_d
->queueCmd(DCframe
, 0, DebuggerDriver::QMnormal
);
173 m_programActive
= true;
174 m_haveExecutable
= true;
177 // create a type table
178 m_typeTable
= new ProgramTypeTable
;
179 m_sharedLibsListed
= false;
186 void KDebugger::useCoreFile(QString corefile
, bool batch
)
188 m_corefile
= corefile
;
190 CmdQueueItem
* cmd
= loadCoreFile();
191 cmd
->m_byUser
= true;
195 void KDebugger::programRun()
200 // when program is active, but not a core file, continue
201 // otherwise run the program
202 if (m_programActive
&& m_corefile
.isEmpty()) {
203 // gdb command: continue
204 m_d
->executeCmd(DCcont
, true);
207 m_d
->executeCmd(DCrun
, true);
208 m_corefile
= QString();
209 m_programActive
= true;
211 m_programRunning
= true;
214 void KDebugger::attachProgram(const QString
& pid
)
220 TRACE("Attaching to " + m_attachedPid
);
221 m_d
->executeCmd(DCattach
, m_attachedPid
);
222 m_programActive
= true;
223 m_programRunning
= true;
226 void KDebugger::programRunAgain()
228 if (canSingleStep()) {
229 m_d
->executeCmd(DCrun
, true);
230 m_corefile
= QString();
231 m_programRunning
= true;
235 void KDebugger::programStep()
237 if (canSingleStep()) {
238 m_d
->executeCmd(DCstep
, true);
239 m_programRunning
= true;
243 void KDebugger::programNext()
245 if (canSingleStep()) {
246 m_d
->executeCmd(DCnext
, true);
247 m_programRunning
= true;
251 void KDebugger::programFinish()
253 if (canSingleStep()) {
254 m_d
->executeCmd(DCfinish
, true);
255 m_programRunning
= true;
259 void KDebugger::programKill()
261 if (haveExecutable() && isProgramActive()) {
262 if (m_programRunning
) {
263 m_d
->interruptInferior();
265 // this is an emergency command; flush queues
266 m_d
->flushCommands(true);
267 m_d
->executeCmd(DCkill
, true);
271 bool KDebugger::runUntil(const QString
& fileName
, int lineNo
)
273 if (isReady() && m_programActive
&& !m_programRunning
) {
274 // strip off directory part of file name
275 QString file
= fileName
;
279 int offset
= file
.findRev("/");
281 file
.remove(0, offset
+1);
283 m_d
->executeCmd(DCuntil
, file
, lineNo
, true);
284 m_programRunning
= true;
291 void KDebugger::programBreak()
293 if (m_haveExecutable
&& m_programRunning
) {
294 m_d
->interruptInferior();
298 void KDebugger::programArgs()
300 if (m_haveExecutable
) {
301 PgmArgs
dlg(parentWidget(), m_executable
, m_envVars
);
302 dlg
.setArgs(m_programArgs
);
303 dlg
.setWd(m_programWD
);
305 updateProgEnvironment(dlg
.args(), dlg
.wd(), dlg
.envVars());
310 bool KDebugger::setBreakpoint(QString file
, int lineNo
, bool temporary
)
316 Breakpoint
* bp
= breakpointByFilePos(file
, lineNo
);
319 // no such breakpoint, so set a new one
320 // strip off directory part of file name
324 int offset
= file
.findRev("/");
326 file
.remove(0, offset
+1);
328 m_d
->executeCmd(temporary
? DCtbreakline
: DCbreakline
,
334 * If the breakpoint is disabled, enable it; if it's enabled,
335 * delete that breakpoint.
338 m_d
->executeCmd(DCdelete
, bp
->id
);
340 m_d
->executeCmd(DCenable
, bp
->id
);
346 bool KDebugger::enableDisableBreakpoint(QString file
, int lineNo
)
352 Breakpoint
* bp
= breakpointByFilePos(file
, lineNo
);
356 // toggle enabled/disabled state
358 m_d
->executeCmd(DCdisable
, bp
->id
);
360 m_d
->executeCmd(DCenable
, bp
->id
);
365 bool KDebugger::canSingleStep()
367 return isReady() && m_programActive
&& !m_programRunning
;
370 bool KDebugger::canChangeBreakpoints()
372 return isReady() && !m_programRunning
;
375 bool KDebugger::isReady() const
377 return m_haveExecutable
&&
378 m_d
->canExecuteImmediately();
381 bool KDebugger::isIdle() const
383 return m_d
->isIdle();
387 //////////////////////////////////////////////////////////
390 bool KDebugger::startGdb()
392 emit
debuggerStarting(); /* must set m_inferiorTerminal */
395 * If the per-program command string is empty, use the global setting
396 * (which might also be empty, in which case the driver uses its
399 QString debuggerCmd
= m_debuggerCmd
.isEmpty() ?
400 m_generalDebuggerCmd
: m_debuggerCmd
;
401 m_explicitKill
= false;
402 if (!m_d
->startup(debuggerCmd
)) {
407 * If we have an output terminal, we use it. Otherwise we will run the
408 * program with input and output redirected to /dev/null. Other
409 * redirections are also necessary depending on the tty emulation
412 int redirect
= RDNstdin
|RDNstdout
|RDNstderr
; /* redirect everything */
413 if (!m_inferiorTerminal
.isEmpty()) {
414 switch (m_ttyLevel
) {
417 // redirect everything
419 case ttySimpleOutputOnly
:
427 m_d
->executeCmd(DCtty
, m_inferiorTerminal
, redirect
);
432 void KDebugger::stopGdb()
434 m_explicitKill
= true;
438 void KDebugger::gdbExited(KProcess
*)
441 * Save settings, but only if gdb has already processed "info line
442 * main", otherwise we would save an empty config file, because it
443 * isn't read in until then!
445 if (m_programConfig
!= 0) {
446 if (m_haveExecutable
) {
447 saveProgramSettings();
448 m_programConfig
->sync();
450 delete m_programConfig
;
458 if (m_explicitKill
) {
459 TRACE("gdb exited normally");
461 QString msg
= i18n("gdb exited unexpectedly.\n"
462 "Restart the session (e.g. with File|Executable).");
464 KMsgBox::message(parentWidget(), kapp
->appName(), msg
, KMsgBox::EXCLAMATION
);
466 KMessageBox::error(parentWidget(), msg
);
471 m_haveExecutable
= false;
473 m_programActive
= false;
474 m_programRunning
= false;
475 m_explicitKill
= false;
476 m_debuggerCmd
= QString(); /* use global setting at next start! */
477 m_attachedPid
= QString(); /* we are no longer attached to a process */
479 // stop gear wheel and erase PC
481 emit
updatePC(QString(), -1, 0);
484 void KDebugger::openProgramConfig(const QString
& name
)
486 ASSERT(m_programConfig
= 0);
489 QString pgmConfigFile
= fi
.dirPath(true);
490 if (!pgmConfigFile
.isEmpty()) {
491 pgmConfigFile
+= '/';
493 pgmConfigFile
+= ".kdbgrc." + fi
.fileName();
494 TRACE("program config file = " + pgmConfigFile
);
495 // check whether we can write to the file
496 QFile
file(pgmConfigFile
);
497 bool readonly
= true;
499 if (file
.open(IO_ReadWrite
)) { /* don't truncate! */
501 // the file exists now
502 } else if (!file
.open(IO_ReadOnly
)) {
503 /* file does not exist and cannot be created: don't use it */
507 m_programConfig
= new KSimpleConfig(pgmConfigFile
, readonly
);
511 const char EnvironmentGroup
[] = "Environment";
512 const char WatchGroup
[] = "Watches";
513 const char FileVersion
[] = "FileVersion";
514 const char ProgramArgs
[] = "ProgramArgs";
515 const char WorkingDirectory
[] = "WorkingDirectory";
516 const char Variable
[] = "Var%d";
517 const char Value
[] = "Value%d";
518 const char ExprFmt
[] = "Expr%d";
520 void KDebugger::saveProgramSettings()
522 ASSERT(m_programConfig
!= 0);
523 m_programConfig
->setGroup(GeneralGroup
);
524 m_programConfig
->writeEntry(FileVersion
, 1);
525 m_programConfig
->writeEntry(ProgramArgs
, m_programArgs
);
526 m_programConfig
->writeEntry(WorkingDirectory
, m_programWD
);
527 m_programConfig
->writeEntry(DebuggerCmdStr
, m_debuggerCmd
);
528 m_programConfig
->writeEntry(TTYLevelEntry
, int(m_ttyLevel
));
530 // write environment variables
531 m_programConfig
->deleteGroup(EnvironmentGroup
);
532 m_programConfig
->setGroup(EnvironmentGroup
);
533 QDictIterator
<EnvVar
> it
= m_envVars
;
537 for (int i
= 0; (var
= it
) != 0; ++it
, ++i
) {
538 varName
.sprintf(Variable
, i
);
539 varValue
.sprintf(Value
, i
);
540 m_programConfig
->writeEntry(varName
, it
.currentKey());
541 m_programConfig
->writeEntry(varValue
, var
->value
);
544 saveBreakpoints(m_programConfig
);
547 // first get rid of whatever was in this group
548 m_programConfig
->deleteGroup(WatchGroup
);
549 // then start a new group
550 m_programConfig
->setGroup(WatchGroup
);
551 KTreeViewItem
* item
= m_watchVariables
.itemAt(0);
553 for (; item
!= 0; item
= item
->getSibling(), ++watchNum
) {
554 varName
.sprintf(ExprFmt
, watchNum
);
555 m_programConfig
->writeEntry(varName
, item
->getText());
559 void KDebugger::restoreProgramSettings()
561 ASSERT(m_programConfig
!= 0);
562 m_programConfig
->setGroup(GeneralGroup
);
564 * We ignore file version for now we will use it in the future to
565 * distinguish different versions of this configuration file.
567 m_debuggerCmd
= m_programConfig
->readEntry(DebuggerCmdStr
);
568 // m_ttyLevel has been read in already
569 QString pgmArgs
= m_programConfig
->readEntry(ProgramArgs
);
570 QString pgmWd
= m_programConfig
->readEntry(WorkingDirectory
);
572 // read environment variables
573 m_programConfig
->setGroup(EnvironmentGroup
);
575 QDict
<EnvVar
> pgmVars
;
579 for (int i
= 0;; ++i
) {
580 varName
.sprintf(Variable
, i
);
581 varValue
.sprintf(Value
, i
);
582 if (!m_programConfig
->hasKey(varName
)) {
583 /* entry not present, assume that we've hit them all */
586 QString name
= m_programConfig
->readEntry(varName
);
587 if (name
.isEmpty()) {
592 var
->value
= m_programConfig
->readEntry(varValue
);
593 var
->status
= EnvVar::EVnew
;
594 pgmVars
.insert(name
, var
);
597 updateProgEnvironment(pgmArgs
, pgmWd
, pgmVars
);
599 restoreBreakpoints(m_programConfig
);
602 m_programConfig
->setGroup(WatchGroup
);
603 m_watchVariables
.clear();
604 for (int i
= 0;; ++i
) {
605 varName
.sprintf(ExprFmt
, i
);
606 if (!m_programConfig
->hasKey(varName
)) {
607 /* entry not present, assume that we've hit them all */
610 QString expr
= m_programConfig
->readEntry(varName
);
611 if (expr
.isEmpty()) {
612 // skip empty expressions
620 * Breakpoints are saved one per group.
622 const char BPGroup
[] = "Breakpoint %d";
623 const char File
[] = "File";
624 const char Line
[] = "Line";
625 const char Temporary
[] = "Temporary";
626 const char Enabled
[] = "Enabled";
627 const char Condition
[] = "Condition";
629 void KDebugger::saveBreakpoints(KSimpleConfig
* config
)
633 for (i
= 0; uint(i
) < m_brkpts
.size(); i
++) {
634 groupName
.sprintf(BPGroup
, i
);
635 config
->setGroup(groupName
);
636 Breakpoint
* bp
= m_brkpts
[i
];
637 config
->writeEntry(File
, bp
->fileName
);
638 config
->writeEntry(Line
, bp
->lineNo
);
639 config
->writeEntry(Temporary
, bp
->temporary
);
640 config
->writeEntry(Enabled
, bp
->enabled
);
641 if (bp
->condition
.isEmpty())
642 config
->deleteEntry(Condition
, false);
644 config
->writeEntry(Condition
, bp
->condition
);
645 // we do not save the ignore count
647 // delete remaining groups
648 // we recognize that a group is present if there is an Enabled entry
650 groupName
.sprintf(BPGroup
, i
);
651 config
->setGroup(groupName
);
652 if (!config
->hasKey(Enabled
)) {
653 /* group not present, assume that we've hit them all */
656 config
->deleteGroup(groupName
);
660 void KDebugger::restoreBreakpoints(KSimpleConfig
* config
)
665 bool enabled
, temporary
;
668 * We recognize the end of the list if there is no Enabled entry
671 for (int i
= 0;; i
++) {
672 groupName
.sprintf(BPGroup
, i
);
673 config
->setGroup(groupName
);
674 if (!config
->hasKey(Enabled
)) {
675 /* group not present, assume that we've hit them all */
678 fileName
= config
->readEntry(File
);
679 lineNo
= config
->readNumEntry(Line
, -1);
680 if (lineNo
< 0 || fileName
.isEmpty())
682 enabled
= config
->readBoolEntry(Enabled
, true);
683 temporary
= config
->readBoolEntry(Temporary
, false);
684 condition
= config
->readEntry(Condition
);
686 * Add the breakpoint. We assume that we have started a new
687 * instance of gdb, because we assign the breakpoint ids ourselves,
688 * starting with 1. Then we use this id to disable the breakpoint,
689 * if necessary. If this assignment of ids doesn't work, (maybe
690 * because this isn't a fresh gdb at all), we disable the wrong
691 * breakpoint! Oh well... for now it works.
693 m_d
->executeCmd(temporary
? DCtbreakline
: DCbreakline
,
696 m_d
->executeCmd(DCdisable
, i
+1);
698 if (!condition
.isEmpty()) {
699 m_d
->executeCmd(DCcondition
, condition
, i
+1);
702 m_d
->queueCmd(DCinfobreak
, DebuggerDriver::QMoverride
);
706 // parse output of command cmd
707 void KDebugger::parse(CmdQueueItem
* cmd
, const char* output
)
709 ASSERT(cmd
!= 0); /* queue mustn't be empty */
711 TRACE(QString(__PRETTY_FUNCTION__
) + " parsing " + output
);
713 switch (cmd
->m_cmd
) {
715 // the output (if any) is uninteresting
718 // there is no output
721 /* if value is empty, we see output, but we don't care */
724 /* display gdb's message in the status bar */
725 m_d
->parseChangeWD(output
, m_statusMessage
);
726 emit
updateStatusMessage();
731 if (m_d
->parseChangeExecutable(output
, m_statusMessage
))
733 // success; restore breakpoints etc.
734 if (m_programConfig
!= 0) {
735 restoreProgramSettings();
737 // load file containing main() or core file
738 if (m_corefile
.isEmpty()) {
739 if (m_remoteDevice
.isEmpty())
740 m_d
->queueCmd(DCinfolinemain
, DebuggerDriver::QMnormal
);
745 if (!m_statusMessage
.isEmpty())
746 emit
updateStatusMessage();
748 QString msg
= "gdb: " + m_statusMessage
;
750 KMsgBox::message(parentWidget(), kapp
->appName(), msg
,
751 KMsgBox::STOP
, i18n("OK"));
753 KMessageBox::sorry(parentWidget(), msg
);
756 m_corefile
= ""; /* don't process core file */
757 m_haveExecutable
= false;
761 // in any event we have an executable at this point
762 m_haveExecutable
= true;
763 if (m_d
->parseCoreFile(output
)) {
764 // loading a core is like stopping at a breakpoint
765 m_programActive
= true;
766 handleRunCommands(output
);
767 // do not reset m_corefile
770 QString msg
= m_d
->driverName() + ": " + QString(output
);
772 KMsgBox::message(parentWidget(), kapp
->appName(), msg
,
773 KMsgBox::EXCLAMATION
, i18n("OK"));
775 KMessageBox::sorry(parentWidget(), msg
);
777 // if core file was loaded from command line, revert to info line main
778 if (!cmd
->m_byUser
) {
779 m_d
->queueCmd(DCinfolinemain
, DebuggerDriver::QMnormal
);
781 m_corefile
= QString(); /* core file not available any more */
785 // ignore the output, marked file info follows
786 m_haveExecutable
= true;
789 // parse local variables
790 if (output
[0] != '\0') {
791 handleLocals(output
);
794 case DCinforegisters
:
795 handleRegisters(output
);
798 handleFrameChange(output
);
802 handleBacktrace(output
);
806 handlePrint(cmd
, output
);
815 handleRunCommands(output
);
818 m_programRunning
= m_programActive
= false;
820 emit
updatePC(QString(), -1, 0);
825 newBreakpoint(output
);
830 // these commands need immediate response
831 m_d
->queueCmd(DCinfobreak
, DebuggerDriver::QMoverrideMoreEqual
);
834 // note: this handler must not enqueue a command, since
835 // DCinfobreak is used at various different places.
836 updateBreakList(output
);
837 emit
lineItemsChanged();
840 handleFindType(cmd
, output
);
843 case DCprintQStringStruct
:
844 handlePrintStruct(cmd
, output
);
846 case DCinfosharedlib
:
847 handleSharedLibs(output
);
851 // we are not interested in the output
856 void KDebugger::backgroundUpdate()
859 * If there are still expressions that need to be updated, then do so.
865 void KDebugger::handleRunCommands(const char* output
)
867 uint flags
= m_d
->parseProgramStopped(output
, m_statusMessage
);
868 emit
updateStatusMessage();
870 m_programActive
= flags
& DebuggerDriver::SFprogramActive
;
872 // refresh files if necessary
873 if (flags
& DebuggerDriver::SFrefreshSource
) {
874 TRACE("re-reading files");
875 emit
executableUpdated();
879 * If we stopped at a breakpoint, we must update the breakpoint list
880 * because the hit count changes. Also, if the breakpoint was temporary
881 * it would go away now.
883 if ((flags
& (DebuggerDriver::SFrefreshBreak
|DebuggerDriver::SFrefreshSource
)) ||
886 m_d
->queueCmd(DCinfobreak
, DebuggerDriver::QMoverride
);
890 * If we haven't listed the shared libraries yet, do so. We must do
891 * this before we emit any commands that list variables, since the type
892 * libraries depend on the shared libraries.
894 if (!m_sharedLibsListed
) {
895 // must be a high-priority command!
896 m_d
->executeCmd(DCinfosharedlib
);
899 // get the backtrace if the program is running
900 if (m_programActive
) {
901 m_d
->queueCmd(DCbt
, DebuggerDriver::QMoverride
);
903 // program finished: erase PC
904 emit
updatePC(QString(), -1, 0);
905 // dequeue any commands in the queues
906 m_d
->flushCommands();
909 m_programRunning
= false;
912 void KDebugger::slotInferiorRunning()
914 m_programRunning
= true;
917 void KDebugger::updateAllExprs()
919 if (!m_programActive
)
922 // retrieve local variables
923 m_d
->queueCmd(DCinfolocals
, DebuggerDriver::QMoverride
);
925 // retrieve registers
926 m_d
->queueCmd(DCinforegisters
, DebuggerDriver::QMoverride
);
928 // update watch expressions
929 KTreeViewItem
* item
= m_watchVariables
.itemAt(0);
930 for (; item
!= 0; item
= item
->getSibling()) {
931 m_watchEvalExpr
.append(static_cast<VarTree
*>(item
));
935 void KDebugger::updateProgEnvironment(const QString
& args
, const QString
& wd
,
936 const QDict
<EnvVar
>& newVars
)
938 m_programArgs
= args
;
939 m_d
->executeCmd(DCsetargs
, m_programArgs
);
940 TRACE("new pgm args: " + m_programArgs
+ "\n");
942 m_programWD
= wd
.stripWhiteSpace();
943 if (!m_programWD
.isEmpty()) {
944 m_d
->executeCmd(DCcd
, m_programWD
);
945 TRACE("new wd: " + m_programWD
+ "\n");
948 QDictIterator
<EnvVar
> it
= newVars
;
950 for (; (val
= it
) != 0; ++it
) {
951 switch (val
->status
) {
953 m_envVars
.insert(it
.currentKey(), val
);
955 case EnvVar::EVdirty
:
956 // the value must be in our list
957 ASSERT(m_envVars
[it
.currentKey()] == val
);
959 m_d
->executeCmd(DCsetenv
, it
.currentKey(), val
->value
);
961 case EnvVar::EVdeleted
:
962 // must be in our list
963 ASSERT(m_envVars
[it
.currentKey()] == val
);
965 m_d
->executeCmd(DCsetenv
, it
.currentKey());
966 m_envVars
.remove(it
.currentKey());
970 case EnvVar::EVclean
:
971 // variable not changed
977 void KDebugger::handleLocals(const char* output
)
979 // retrieve old list of local variables
981 m_localVariables
.exprList(oldVars
);
984 * Get local variables.
986 QList
<VarTree
> newVars
;
987 parseLocals(output
, newVars
);
990 * Clear any old VarTree item pointers, so that later we don't access
993 m_localVariables
.clearPendingUpdates();
996 bool autoU
= m_localVariables
.autoUpdate();
997 m_localVariables
.setAutoUpdate(false);
998 bool repaintNeeded
= false;
1001 * Match old variables against new ones.
1003 for (const char* n
= oldVars
.first(); n
!= 0; n
= oldVars
.next()) {
1004 // lookup this variable in the list of new variables
1005 VarTree
* v
= newVars
.first();
1006 while (v
!= 0 && strcmp(v
->getText(), n
) != 0) {
1010 // old variable not in the new variables
1011 TRACE(QString("old var deleted: ") + n
);
1012 v
= m_localVariables
.topLevelExprByName(n
);
1013 removeExpr(&m_localVariables
, v
);
1014 if (v
!= 0) repaintNeeded
= true;
1016 // variable in both old and new lists: update
1017 TRACE(QString("update var: ") + n
);
1018 m_localVariables
.updateExpr(newVars
.current());
1019 // remove the new variable from the list
1022 #if QT_VERSION >= 200
1023 repaintNeeded
= true;
1027 // insert all remaining new variables
1028 for (VarTree
* v
= newVars
.first(); v
!= 0; v
= newVars
.next()) {
1029 TRACE("new var: " + v
->getText());
1030 m_localVariables
.insertExpr(v
);
1031 repaintNeeded
= true;
1035 m_localVariables
.setAutoUpdate(autoU
);
1036 if (repaintNeeded
&& autoU
&& m_localVariables
.isVisible())
1037 m_localVariables
.repaint();
1040 void KDebugger::parseLocals(const char* output
, QList
<VarTree
>& newVars
)
1042 QList
<VarTree
> vars
;
1043 m_d
->parseLocals(output
, vars
);
1045 QString origName
; /* used in renaming variables */
1046 while (vars
.count() > 0)
1048 VarTree
* variable
= vars
.take(0);
1050 variable
->inferTypesOfChildren(*m_typeTable
);
1052 * When gdb prints local variables, those from the innermost block
1053 * come first. We run through the list of already parsed variables
1054 * to find duplicates (ie. variables that hide local variables from
1055 * a surrounding block). We keep the name of the inner variable, but
1056 * rename those from the outer block so that, when the value is
1057 * updated in the window, the value of the variable that is
1058 * _visible_ changes the color!
1061 origName
= variable
->getText();
1062 for (VarTree
* v
= newVars
.first(); v
!= 0; v
= newVars
.next()) {
1063 if (variable
->getText() == v
->getText()) {
1064 // we found a duplicate, change name
1066 QString newName
= origName
+ " (" + QString().setNum(block
) + ")";
1067 variable
->setText(newName
);
1070 newVars
.append(variable
);
1074 bool KDebugger::handlePrint(CmdQueueItem
* cmd
, const char* output
)
1076 ASSERT(cmd
->m_expr
!= 0);
1078 VarTree
* variable
= parseExpr(output
, true);
1082 // set expression "name"
1083 variable
->setText(cmd
->m_expr
->getText());
1085 if (cmd
->m_expr
->m_varKind
== VarTree::VKpointer
) {
1087 * We must insert a dummy parent, because otherwise variable's value
1088 * would overwrite cmd->m_expr's value.
1090 VarTree
* dummyParent
= new VarTree(variable
->getText(), VarTree::NKplain
);
1091 dummyParent
->m_varKind
= VarTree::VKdummy
;
1092 // the name of the parsed variable is the address of the pointer
1093 QString addr
= "*" + cmd
->m_expr
->m_value
;
1094 variable
->setText(addr
);
1095 variable
->m_nameKind
= VarTree::NKaddress
;
1097 dummyParent
->appendChild(variable
);
1098 dummyParent
->setDeleteChildren(true);
1099 TRACE("update ptr: " + cmd
->m_expr
->getText());
1100 cmd
->m_exprWnd
->updateExpr(cmd
->m_expr
, dummyParent
);
1103 TRACE("update expr: " + cmd
->m_expr
->getText());
1104 cmd
->m_exprWnd
->updateExpr(cmd
->m_expr
, variable
);
1108 evalExpressions(); /* enqueue dereferenced pointers */
1113 VarTree
* KDebugger::parseExpr(const char* output
, bool wantErrorValue
)
1117 // check for error conditions
1118 bool goodValue
= m_d
->parsePrintExpr(output
, wantErrorValue
, variable
);
1120 if (variable
!= 0 && goodValue
)
1123 variable
->inferTypesOfChildren(*m_typeTable
);
1128 // parse the output of bt
1129 void KDebugger::handleBacktrace(const char* output
)
1132 m_btWindow
.setAutoUpdate(false);
1136 QList
<StackFrame
> stack
;
1137 m_d
->parseBackTrace(output
, stack
);
1139 if (stack
.count() > 0) {
1140 StackFrame
* frm
= stack
.take(0);
1141 // first frame must set PC
1142 // note: frm->lineNo is zero-based
1143 emit
updatePC(frm
->fileName
, frm
->lineNo
, frm
->frameNo
);
1148 func
= frm
->var
->getText();
1150 func
= frm
->fileName
+ ":" + QString().setNum(frm
->lineNo
+1);
1151 m_btWindow
.insertItem(func
);
1152 TRACE("frame " + func
+ " (" + frm
->fileName
+ ":" +
1153 QString().setNum(frm
->lineNo
+1) + ")");
1156 while ((frm
= stack
.take()) != 0);
1159 m_btWindow
.setAutoUpdate(true);
1160 m_btWindow
.repaint();
1163 void KDebugger::gotoFrame(int frame
)
1165 m_d
->executeCmd(DCframe
, frame
);
1168 void KDebugger::handleFrameChange(const char* output
)
1173 if (m_d
->parseFrameChange(output
, frameNo
, fileName
, lineNo
)) {
1174 /* lineNo can be negative here if we can't find a file name */
1175 emit
updatePC(fileName
, lineNo
, frameNo
);
1177 emit
updatePC(fileName
, -1, frameNo
);
1181 void KDebugger::evalExpressions()
1183 // evaluate expressions in the following order:
1184 // watch expressions
1185 // pointers in local variables
1186 // pointers in watch expressions
1187 // types in local variables
1188 // types in watch expressions
1189 // pointers in 'this'
1192 VarTree
* exprItem
= m_watchEvalExpr
.first();
1193 if (exprItem
!= 0) {
1194 m_watchEvalExpr
.remove();
1195 QString expr
= exprItem
->computeExpr();
1196 TRACE("watch expr: " + expr
);
1197 CmdQueueItem
* cmd
= m_d
->queueCmd(DCprint
, expr
, DebuggerDriver::QMoverride
);
1198 // remember which expr this was
1199 cmd
->m_expr
= exprItem
;
1200 cmd
->m_exprWnd
= &m_watchVariables
;
1204 #define POINTER(widget) \
1206 exprItem = widget.nextUpdatePtr(); \
1207 if (exprItem != 0) goto pointer
1208 #define STRUCT(widget) \
1210 exprItem = widget.nextUpdateStruct(); \
1211 if (exprItem != 0) goto ustruct
1212 #define TYPE(widget) \
1214 exprItem = widget.nextUpdateType(); \
1215 if (exprItem != 0) goto type
1217 POINTER(m_localVariables
);
1218 POINTER(m_watchVariables
);
1219 STRUCT(m_localVariables
);
1220 STRUCT(m_watchVariables
);
1221 TYPE(m_localVariables
);
1222 TYPE(m_watchVariables
);
1229 // we have an expression to send
1230 dereferencePointer(wnd
, exprItem
, false);
1235 if (exprItem
->m_type
== 0 || exprItem
->m_type
== TypeInfo::unknownType())
1237 evalInitialStructExpression(exprItem
, wnd
, false);
1242 * Sometimes a VarTree gets registered twice for a type update. So
1243 * it may happen that it has already been updated. Hence, we ignore
1244 * it here and go on to the next task.
1246 if (exprItem
->m_type
!= 0)
1248 determineType(wnd
, exprItem
);
1252 void KDebugger::dereferencePointer(ExprWnd
* wnd
, VarTree
* exprItem
,
1255 ASSERT(exprItem
->m_varKind
== VarTree::VKpointer
);
1257 QString expr
= exprItem
->computeExpr();
1258 TRACE("dereferencing pointer: " + expr
);
1259 QString queueExpr
= "*(" + expr
+ ")";
1262 cmd
= m_d
->queueCmd(DCprint
, queueExpr
, DebuggerDriver::QMoverrideMoreEqual
);
1264 cmd
= m_d
->queueCmd(DCprint
, queueExpr
, DebuggerDriver::QMoverride
);
1266 // remember which expr this was
1267 cmd
->m_expr
= exprItem
;
1268 cmd
->m_exprWnd
= wnd
;
1271 void KDebugger::determineType(ExprWnd
* wnd
, VarTree
* exprItem
)
1273 ASSERT(exprItem
->m_varKind
== VarTree::VKstruct
);
1275 QString expr
= exprItem
->computeExpr();
1276 TRACE("get type of: " + expr
);
1278 cmd
= m_d
->queueCmd(DCfindType
, expr
, DebuggerDriver::QMoverride
);
1280 // remember which expr this was
1281 cmd
->m_expr
= exprItem
;
1282 cmd
->m_exprWnd
= wnd
;
1285 void KDebugger::handleFindType(CmdQueueItem
* cmd
, const char* output
)
1288 if (m_d
->parseFindType(output
, type
))
1290 ASSERT(cmd
!= 0 && cmd
->m_expr
!= 0);
1292 TypeInfo
* info
= m_typeTable
->lookup(type
);
1296 * We've asked gdb for the type of the expression in
1297 * cmd->m_expr, but it returned a name we don't know. The base
1298 * class (and member) types have been checked already (at the
1299 * time when we parsed that particular expression). Now it's
1300 * time to derive the type from the base classes as a last
1303 info
= cmd
->m_expr
->inferTypeFromBaseClass();
1304 // if we found a type through this method, register an alias
1306 TRACE("infered alias: " + type
);
1307 m_typeTable
->registerAlias(type
, info
);
1311 TRACE("unknown type");
1312 cmd
->m_expr
->m_type
= TypeInfo::unknownType();
1314 cmd
->m_expr
->m_type
= info
;
1315 /* since this node has a new type, we get its value immediately */
1316 evalInitialStructExpression(cmd
->m_expr
, cmd
->m_exprWnd
, false);
1321 evalExpressions(); /* queue more of them */
1324 void KDebugger::handlePrintStruct(CmdQueueItem
* cmd
, const char* output
)
1326 VarTree
* var
= cmd
->m_expr
;
1328 ASSERT(var
->m_varKind
== VarTree::VKstruct
);
1331 if (cmd
->m_cmd
!= DCprintQStringStruct
) {
1332 partExpr
= parseExpr(output
, false);
1334 partExpr
= m_d
->parseQCharArray(output
, false);
1338 /* we only allow simple values at the moment */
1339 partExpr
->childCount() != 0;
1346 partValue
= partExpr
->m_value
;
1352 * Updating a struct value works like this: var->m_partialValue holds
1353 * the value that we have gathered so far (it's been initialized with
1354 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1355 * we append the printed result followed by the next
1356 * var->m_type->m_displayString to var->m_partialValue.
1358 * If the expression we just evaluated was a guard expression, and it
1359 * resulted in an error, we must not evaluate the real expression, but
1360 * go on to the next index. (We must still add the ??? to the value).
1362 * Next, if this was the length expression, we still have not seen the
1363 * real expression, but the length of a QString.
1365 ASSERT(var
->m_exprIndex
>= 0 && var
->m_exprIndex
<= typeInfoMaxExpr
);
1367 if (errorValue
|| !var
->m_exprIndexUseGuard
)
1369 // add current partValue (which might be ???)
1370 #if QT_VERSION < 200
1371 var
->m_partialValue
.detach();
1373 var
->m_partialValue
+= partValue
;
1374 var
->m_exprIndex
++; /* next part */
1375 var
->m_exprIndexUseGuard
= true;
1376 var
->m_partialValue
+= var
->m_type
->m_displayString
[var
->m_exprIndex
];
1380 // this was a guard expression that succeeded
1381 // go for the real expression
1382 var
->m_exprIndexUseGuard
= false;
1385 /* go for more sub-expressions if needed */
1386 if (var
->m_exprIndex
< var
->m_type
->m_numExprs
) {
1387 /* queue a new print command with quite high priority */
1388 evalStructExpression(var
, cmd
->m_exprWnd
, true);
1392 cmd
->m_exprWnd
->updateStructValue(var
);
1394 evalExpressions(); /* enqueue dereferenced pointers */
1397 /* queues the first printStruct command for a struct */
1398 void KDebugger::evalInitialStructExpression(VarTree
* var
, ExprWnd
* wnd
, bool immediate
)
1400 var
->m_exprIndex
= 0;
1401 var
->m_exprIndexUseGuard
= true;
1402 var
->m_partialValue
= var
->m_type
->m_displayString
[0];
1403 evalStructExpression(var
, wnd
, immediate
);
1406 /* queues a printStruct command; var must have been initialized correctly */
1407 void KDebugger::evalStructExpression(VarTree
* var
, ExprWnd
* wnd
, bool immediate
)
1409 QString base
= var
->computeExpr();
1411 if (var
->m_exprIndexUseGuard
) {
1412 exprFmt
= var
->m_type
->m_guardStrings
[var
->m_exprIndex
];
1413 if (exprFmt
.isEmpty()) {
1414 // no guard, omit it and go to expression
1415 var
->m_exprIndexUseGuard
= false;
1418 if (!var
->m_exprIndexUseGuard
) {
1419 exprFmt
= var
->m_type
->m_exprStrings
[var
->m_exprIndex
];
1422 SIZED_QString(expr
, exprFmt
.length() + base
.length() + 10);
1423 expr
.sprintf(exprFmt
, base
.data());
1425 DbgCommand dbgCmd
= DCprintStruct
;
1426 // check if this is a QString::Data
1427 if (strncmp(expr
, "/QString::Data ", 15) == 0)
1429 if (m_typeTable
->parseQt2QStrings())
1431 expr
= expr
.mid(15, expr
.length()); /* strip off /QString::Data */
1432 dbgCmd
= DCprintQStringStruct
;
1435 * This should not happen: the type libraries should be set up
1436 * in a way that this can't happen. If this happens
1437 * nevertheless it means that, eg., kdecore was loaded but qt2
1438 * was not (only qt2 enables the QString feature).
1440 // TODO: remove this "print"; queue the next printStruct instead
1446 TRACE("evalStruct: " + expr
+ (var
->m_exprIndexUseGuard
? " // guard" : " // real"));
1447 CmdQueueItem
* cmd
= m_d
->queueCmd(dbgCmd
, expr
,
1448 immediate
? DebuggerDriver::QMoverrideMoreEqual
1449 : DebuggerDriver::QMnormal
);
1451 // remember which expression this was
1453 cmd
->m_exprWnd
= wnd
;
1456 /* removes expression from window */
1457 void KDebugger::removeExpr(ExprWnd
* wnd
, VarTree
* var
)
1462 // must remove any references to var from command queues
1463 m_d
->dequeueCmdByVar(var
);
1465 wnd
->removeExpr(var
);
1468 void KDebugger::handleSharedLibs(const char* output
)
1470 // delete all known libraries
1471 m_sharedLibs
.clear();
1473 // parse the table of shared libraries
1474 m_d
->parseSharedLibs(output
, m_sharedLibs
);
1475 m_sharedLibsListed
= true;
1477 // get type libraries
1478 m_typeTable
->loadLibTypes(m_sharedLibs
);
1481 CmdQueueItem
* KDebugger::loadCoreFile()
1483 return m_d
->queueCmd(DCcorefile
, m_corefile
, DebuggerDriver::QMoverride
);
1486 void KDebugger::slotLocalsExpanding(KTreeViewItem
* item
, bool& allow
)
1488 exprExpandingHelper(&m_localVariables
, item
, allow
);
1491 void KDebugger::slotWatchExpanding(KTreeViewItem
* item
, bool& allow
)
1493 exprExpandingHelper(&m_watchVariables
, item
, allow
);
1496 void KDebugger::exprExpandingHelper(ExprWnd
* wnd
, KTreeViewItem
* item
, bool&)
1498 VarTree
* exprItem
= static_cast<VarTree
*>(item
);
1499 if (exprItem
->m_varKind
!= VarTree::VKpointer
) {
1502 dereferencePointer(wnd
, exprItem
, true);
1505 // add the expression in the edit field to the watch expressions
1506 void KDebugger::addWatch(const QString
& t
)
1508 QString expr
= t
.stripWhiteSpace();
1511 VarTree
* exprItem
= new VarTree(expr
, VarTree::NKplain
);
1512 m_watchVariables
.insertExpr(exprItem
);
1514 // if we are boring ourselves, send down the command
1515 if (m_programActive
) {
1516 m_watchEvalExpr
.append(exprItem
);
1517 if (m_d
->isIdle()) {
1523 // delete a toplevel watch expression
1524 void KDebugger::slotDeleteWatch()
1526 // delete only allowed while debugger is idle; or else we might delete
1527 // the very expression the debugger is currently working on...
1531 int index
= m_watchVariables
.currentItem();
1535 VarTree
* item
= static_cast<VarTree
*>(m_watchVariables
.itemAt(index
));
1536 if (!item
->isToplevelExpr())
1539 // remove the variable from the list to evaluate
1540 if (m_watchEvalExpr
.findRef(item
) >= 0) {
1541 m_watchEvalExpr
.remove();
1543 removeExpr(&m_watchVariables
, item
);
1544 // item is invalid at this point!
1547 void KDebugger::startAnimation(bool fast
)
1549 int interval
= fast
? 50 : 150;
1550 if (!m_animationTimer
.isActive()) {
1551 m_animationTimer
.start(interval
);
1552 } else if (m_animationInterval
!= interval
) {
1553 m_animationTimer
.changeInterval(interval
);
1555 m_animationInterval
= interval
;
1558 void KDebugger::stopAnimation()
1560 if (m_animationTimer
.isActive()) {
1561 m_animationTimer
.stop();
1562 m_animationInterval
= 0;
1566 void KDebugger::slotUpdateAnimation()
1568 if (m_d
->isIdle()) {
1572 * Slow animation while program is stopped (i.e. while variables
1575 bool slow
= isReady() && m_programActive
&& !m_programRunning
;
1576 startAnimation(!slow
);
1580 void KDebugger::handleRegisters(const char* output
)
1582 QList
<RegisterInfo
> regs
;
1583 m_d
->parseRegisters(output
, regs
);
1585 emit
registersChanged(regs
);
1588 regs
.setAutoDelete(true);
1592 * The output of the DCbreak* commands has more accurate information about
1593 * the file and the line number.
1595 void KDebugger::newBreakpoint(const char* output
)
1600 if (!m_d
->parseBreakpoint(output
, id
, file
, lineNo
))
1604 for (int i
= m_brkpts
.size()-1; i
>= 0; i
--) {
1605 if (m_brkpts
[i
]->id
== id
) {
1607 m_brkpts
[i
]->fileName
= file
;
1608 m_brkpts
[i
]->lineNo
= lineNo
;
1613 Breakpoint
* bp
= new Breakpoint
;
1615 bp
->temporary
= false;
1618 bp
->ignoreCount
= 0;
1619 bp
->fileName
= file
;
1620 bp
->lineNo
= lineNo
;
1621 int n
= m_brkpts
.size();
1622 m_brkpts
.resize(n
+1);
1626 void KDebugger::updateBreakList(const char* output
)
1629 QList
<Breakpoint
> brks
;
1630 brks
.setAutoDelete(false);
1631 m_d
->parseBreakList(output
, brks
);
1633 // merge new information into existing breakpoints
1635 QArray
<Breakpoint
*> oldbrks
= m_brkpts
;
1637 // move parsed breakpoints into m_brkpts
1639 m_brkpts
.resize(brks
.count());
1641 for (Breakpoint
* bp
= brks
.first(); bp
!= 0; bp
= brks
.next())
1646 // go through all old breakpoints
1647 for (int i
= oldbrks
.size()-1; i
>= 0; i
--) {
1648 // is this one still alive?
1649 for (int j
= m_brkpts
.size()-1; j
>= 0; j
--)
1651 if (m_brkpts
[j
]->id
== oldbrks
[i
]->id
) {
1653 // keep accurate location
1654 m_brkpts
[j
]->fileName
= oldbrks
[i
]->fileName
;
1655 m_brkpts
[j
]->lineNo
= oldbrks
[i
]->lineNo
;
1661 // delete old breakpoints
1662 for (int i
= oldbrks
.size()-1; i
>= 0; i
--) {
1666 emit
breakpointsChanged();
1669 // look if there is at least one temporary breakpoint
1670 bool KDebugger::haveTemporaryBP() const
1672 for (int i
= m_brkpts
.size()-1; i
>= 0; i
--) {
1673 if (m_brkpts
[i
]->temporary
)
1679 Breakpoint
* KDebugger::breakpointByFilePos(QString file
, int lineNo
)
1681 // look for exact file name match
1683 for (i
= m_brkpts
.size()-1; i
>= 0; i
--) {
1684 if (m_brkpts
[i
]->lineNo
== lineNo
&&
1685 m_brkpts
[i
]->fileName
== file
)
1690 // not found, so try basename
1691 // strip off directory part of file name
1692 int offset
= file
.findRev("/");
1694 // that was already the basename, no need to scan the list again
1697 #if QT_VERSION < 200
1700 file
.remove(0, offset
+1);
1702 for (i
= m_brkpts
.size()-1; i
>= 0; i
--) {
1703 if (m_brkpts
[i
]->lineNo
== lineNo
&&
1704 m_brkpts
[i
]->fileName
== file
)
1714 void KDebugger::slotValuePopup(const QString
& expr
)
1716 // search the local variables for a match
1717 VarTree
* v
= m_localVariables
.topLevelExprByName(expr
);
1719 // not found, check watch expressions
1720 v
= m_watchVariables
.topLevelExprByName(expr
);
1722 // nothing found; do nothing
1727 // construct the tip
1728 QString tip
= v
->getText() + " = ";
1729 if (!v
->m_value
.isEmpty())
1735 // no value: we use some hint
1736 switch (v
->m_varKind
) {
1737 case VarTree::VKstruct
:
1740 case VarTree::VKarray
:
1748 emit
valuePopup(tip
);
1752 #include "debugger.moc"