3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
11 #include "pgmsettings.h"
14 #include <qfileinfo.h>
17 #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_memoryFormat(MDTword
| MDThex
),
42 m_haveExecutable(false),
43 m_programActive(false),
44 m_programRunning(false),
45 m_sharedLibsListed(false),
49 m_localVariables(*localVars
),
50 m_watchVariables(*watchVars
),
51 m_btWindow(*backtrace
),
52 m_animationTimer(this),
53 m_animationInterval(0)
55 m_envVars
.setAutoDelete(true);
57 connect(&m_localVariables
, SIGNAL(expanding(KTreeViewItem
*,bool&)),
58 SLOT(slotLocalsExpanding(KTreeViewItem
*,bool&)));
59 connect(&m_watchVariables
, SIGNAL(expanding(KTreeViewItem
*,bool&)),
60 SLOT(slotWatchExpanding(KTreeViewItem
*,bool&)));
62 connect(&m_btWindow
, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
64 connect(m_d
, SIGNAL(activateFileLine(const QString
&,int,const DbgAddr
&)),
65 this, SIGNAL(activateFileLine(const QString
&,int,const DbgAddr
&)));
68 connect(m_d
, SIGNAL(processExited(KProcess
*)), SLOT(gdbExited(KProcess
*)));
69 connect(m_d
, SIGNAL(commandReceived(CmdQueueItem
*,const char*)),
70 SLOT(parse(CmdQueueItem
*,const char*)));
71 connect(m_d
, SIGNAL(wroteStdin(KProcess
*)), SIGNAL(updateUI()));
72 connect(m_d
, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
73 connect(m_d
, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
74 connect(m_d
, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
77 connect(&m_animationTimer
, SIGNAL(timeout()), SIGNAL(animationTimeout()));
78 // special update of animation
79 connect(this, SIGNAL(updateUI()), SLOT(slotUpdateAnimation()));
84 KDebugger::~KDebugger()
86 if (m_programConfig
!= 0) {
87 saveProgramSettings();
88 m_programConfig
->sync();
89 delete m_programConfig
;
91 // delete breakpoint objects
92 for (int i
= m_brkpts
.size()-1; i
>= 0; i
--) {
100 void KDebugger::saveSettings(KConfig
* /*config*/)
104 void KDebugger::restoreSettings(KConfig
* /*config*/)
109 //////////////////////////////////////////////////////////////////////
110 // external interface
112 const char GeneralGroup
[] = "General";
113 const char DebuggerCmdStr
[] = "DebuggerCmdStr";
114 const char TTYLevelEntry
[] = "TTYLevel";
116 bool KDebugger::debugProgram(const QString
& name
)
118 if (m_d
->isRunning())
120 QApplication::setOverrideCursor(waitCursor
);
124 QApplication::restoreOverrideCursor();
126 if (m_d
->isRunning() || m_haveExecutable
) {
127 /* timed out! We can't really do anything useful now */
128 TRACE("timed out while waiting for gdb to die!");
133 // create the program settings object
134 openProgramConfig(name
);
136 // get debugger command from per-program settings
137 if (m_programConfig
!= 0) {
138 m_programConfig
->setGroup(GeneralGroup
);
139 m_debuggerCmd
= m_programConfig
->readEntry(DebuggerCmdStr
);
140 // get terminal emulation level
141 m_ttyLevel
= TTYLevel(m_programConfig
->readNumEntry(TTYLevelEntry
, ttyFull
));
143 // the rest is read in later in the handler of DCexecutable
145 if (!startDriver()) {
146 TRACE("startDriver failed");
150 TRACE("before file cmd");
151 m_d
->executeCmd(DCexecutable
, name
);
155 if (!m_remoteDevice
.isEmpty()) {
156 m_d
->executeCmd(DCtargetremote
, m_remoteDevice
);
157 m_d
->queueCmd(DCbt
, DebuggerDriver::QMoverride
);
158 m_d
->queueCmd(DCframe
, 0, DebuggerDriver::QMnormal
);
159 m_programActive
= true;
160 m_haveExecutable
= true;
163 // create a type table
164 m_typeTable
= new ProgramTypeTable
;
165 m_sharedLibsListed
= false;
172 void KDebugger::shutdown()
174 // shut down debugger driver
175 if (m_d
->isRunning())
181 void KDebugger::useCoreFile(QString corefile
, bool batch
)
183 m_corefile
= corefile
;
185 CmdQueueItem
* cmd
= loadCoreFile();
186 cmd
->m_byUser
= true;
190 void KDebugger::programRun()
195 // when program is active, but not a core file, continue
196 // otherwise run the program
197 if (m_programActive
&& m_corefile
.isEmpty()) {
198 // gdb command: continue
199 m_d
->executeCmd(DCcont
, true);
202 m_d
->executeCmd(DCrun
, true);
203 m_corefile
= QString();
204 m_programActive
= true;
206 m_programRunning
= true;
209 void KDebugger::attachProgram(const QString
& pid
)
215 TRACE("Attaching to " + m_attachedPid
);
216 m_d
->executeCmd(DCattach
, m_attachedPid
);
217 m_programActive
= true;
218 m_programRunning
= true;
221 void KDebugger::programRunAgain()
223 if (canSingleStep()) {
224 m_d
->executeCmd(DCrun
, true);
225 m_corefile
= QString();
226 m_programRunning
= true;
230 void KDebugger::programStep()
232 if (canSingleStep()) {
233 m_d
->executeCmd(DCstep
, true);
234 m_programRunning
= true;
238 void KDebugger::programNext()
240 if (canSingleStep()) {
241 m_d
->executeCmd(DCnext
, true);
242 m_programRunning
= true;
246 void KDebugger::programStepi()
248 if (canSingleStep()) {
249 m_d
->executeCmd(DCstepi
, true);
250 m_programRunning
= true;
254 void KDebugger::programNexti()
256 if (canSingleStep()) {
257 m_d
->executeCmd(DCnexti
, true);
258 m_programRunning
= true;
262 void KDebugger::programFinish()
264 if (canSingleStep()) {
265 m_d
->executeCmd(DCfinish
, true);
266 m_programRunning
= true;
270 void KDebugger::programKill()
272 if (haveExecutable() && isProgramActive()) {
273 if (m_programRunning
) {
274 m_d
->interruptInferior();
276 // this is an emergency command; flush queues
277 m_d
->flushCommands(true);
278 m_d
->executeCmd(DCkill
, true);
282 bool KDebugger::runUntil(const QString
& fileName
, int lineNo
)
284 if (isReady() && m_programActive
&& !m_programRunning
) {
285 // strip off directory part of file name
286 QString file
= fileName
;
290 int offset
= file
.findRev("/");
292 file
.remove(0, offset
+1);
294 m_d
->executeCmd(DCuntil
, file
, lineNo
, true);
295 m_programRunning
= true;
302 void KDebugger::programBreak()
304 if (m_haveExecutable
&& m_programRunning
) {
305 m_d
->interruptInferior();
309 void KDebugger::programArgs(QWidget
* parent
)
311 if (m_haveExecutable
) {
312 PgmArgs
dlg(parent
, m_executable
, m_envVars
);
313 dlg
.setArgs(m_programArgs
);
314 dlg
.setWd(m_programWD
);
316 updateProgEnvironment(dlg
.args(), dlg
.wd(), dlg
.envVars());
321 void KDebugger::programSettings(QWidget
* parent
)
323 if (!m_haveExecutable
)
326 ProgramSettings
dlg(parent
, m_executable
);
328 dlg
.m_chooseDriver
.setDebuggerCmd(m_debuggerCmd
);
329 dlg
.m_output
.setTTYLevel(m_ttyLevel
);
331 if (dlg
.exec() == QDialog::Accepted
)
333 m_debuggerCmd
= dlg
.m_chooseDriver
.debuggerCmd();
334 m_ttyLevel
= TTYLevel(dlg
.m_output
.ttyLevel());
338 bool KDebugger::setBreakpoint(QString file
, int lineNo
,
339 const DbgAddr
& address
, bool temporary
)
345 Breakpoint
* bp
= breakpointByFilePos(file
, lineNo
, address
);
349 * No such breakpoint, so set a new one. If we have an address, we
350 * set the breakpoint exactly there. Otherwise we use the file name
353 if (address
.isEmpty())
355 // strip off directory part of file name
359 int offset
= file
.findRev("/");
361 file
.remove(0, offset
+1);
363 m_d
->executeCmd(temporary
? DCtbreakline
: DCbreakline
,
368 m_d
->executeCmd(temporary
? DCtbreakaddr
: DCbreakaddr
,
375 * If the breakpoint is disabled, enable it; if it's enabled,
376 * delete that breakpoint.
379 m_d
->executeCmd(DCdelete
, bp
->id
);
381 m_d
->executeCmd(DCenable
, bp
->id
);
387 bool KDebugger::enableDisableBreakpoint(QString file
, int lineNo
,
388 const DbgAddr
& address
)
394 Breakpoint
* bp
= breakpointByFilePos(file
, lineNo
, address
);
398 // toggle enabled/disabled state
400 m_d
->executeCmd(DCdisable
, bp
->id
);
402 m_d
->executeCmd(DCenable
, bp
->id
);
407 bool KDebugger::canSingleStep()
409 return isReady() && m_programActive
&& !m_programRunning
;
412 bool KDebugger::canChangeBreakpoints()
414 return isReady() && !m_programRunning
;
417 bool KDebugger::isReady() const
419 return m_haveExecutable
&&
420 m_d
->canExecuteImmediately();
423 bool KDebugger::isIdle() const
425 return m_d
->isIdle();
429 //////////////////////////////////////////////////////////
432 bool KDebugger::startDriver()
434 emit
debuggerStarting(); /* must set m_inferiorTerminal */
437 * If the per-program command string is empty, use the global setting
438 * (which might also be empty, in which case the driver uses its
441 QString debuggerCmd
= m_debuggerCmd
.isEmpty() ?
442 m_generalDebuggerCmd
: m_debuggerCmd
;
443 m_explicitKill
= false;
444 if (!m_d
->startup(debuggerCmd
)) {
449 * If we have an output terminal, we use it. Otherwise we will run the
450 * program with input and output redirected to /dev/null. Other
451 * redirections are also necessary depending on the tty emulation
454 int redirect
= RDNstdin
|RDNstdout
|RDNstderr
; /* redirect everything */
455 if (!m_inferiorTerminal
.isEmpty()) {
456 switch (m_ttyLevel
) {
459 // redirect everything
461 case ttySimpleOutputOnly
:
469 m_d
->executeCmd(DCtty
, m_inferiorTerminal
, redirect
);
474 void KDebugger::stopDriver()
476 m_explicitKill
= true;
478 if (m_attachedPid
.isEmpty()) {
481 m_d
->detachAndTerminate();
485 * We MUST wait until the slot gdbExited() has been called. But to
486 * avoid a deadlock, we wait only for some certain maximum time. Should
487 * this timeout be reached, the only reasonable thing one could do then
490 kapp
->processEvents(1000); /* ideally, this will already shut it down */
491 int maxTime
= 20; /* about 20 seconds */
492 while (m_haveExecutable
&& maxTime
> 0) {
493 // give gdb time to die (and send a SIGCLD)
496 kapp
->processEvents(1000);
500 void KDebugger::gdbExited(KProcess
*)
503 * Save settings, but only if gdb has already processed "info line
504 * main", otherwise we would save an empty config file, because it
505 * isn't read in until then!
507 if (m_programConfig
!= 0) {
508 if (m_haveExecutable
) {
509 saveProgramSettings();
510 m_programConfig
->sync();
512 delete m_programConfig
;
520 if (m_explicitKill
) {
521 TRACE("gdb exited normally");
523 QString msg
= i18n("gdb exited unexpectedly.\n"
524 "Restart the session (e.g. with File|Executable).");
526 KMsgBox::message(parentWidget(), kapp
->appName(), msg
, KMsgBox::EXCLAMATION
);
528 KMessageBox::error(parentWidget(), msg
);
533 m_haveExecutable
= false;
535 m_programActive
= false;
536 m_programRunning
= false;
537 m_explicitKill
= false;
538 m_debuggerCmd
= QString(); /* use global setting at next start! */
539 m_attachedPid
= QString(); /* we are no longer attached to a process */
540 m_ttyLevel
= ttyFull
;
542 // stop gear wheel and erase PC
544 emit
updatePC(QString(), -1, DbgAddr(), 0);
547 void KDebugger::openProgramConfig(const QString
& name
)
549 ASSERT(m_programConfig
== 0);
552 QString pgmConfigFile
= fi
.dirPath(true);
553 if (!pgmConfigFile
.isEmpty()) {
554 pgmConfigFile
+= '/';
556 pgmConfigFile
+= ".kdbgrc." + fi
.fileName();
557 TRACE("program config file = " + pgmConfigFile
);
558 // check whether we can write to the file
559 QFile
file(pgmConfigFile
);
560 bool readonly
= true;
562 if (file
.open(IO_ReadWrite
)) { /* don't truncate! */
564 // the file exists now
565 } else if (!file
.open(IO_ReadOnly
)) {
566 /* file does not exist and cannot be created: don't use it */
570 m_programConfig
= new KSimpleConfig(pgmConfigFile
, readonly
);
574 const char EnvironmentGroup
[] = "Environment";
575 const char WatchGroup
[] = "Watches";
576 const char FileVersion
[] = "FileVersion";
577 const char ProgramArgs
[] = "ProgramArgs";
578 const char WorkingDirectory
[] = "WorkingDirectory";
579 const char Variable
[] = "Var%d";
580 const char Value
[] = "Value%d";
581 const char ExprFmt
[] = "Expr%d";
583 void KDebugger::saveProgramSettings()
585 ASSERT(m_programConfig
!= 0);
586 m_programConfig
->setGroup(GeneralGroup
);
587 m_programConfig
->writeEntry(FileVersion
, 1);
588 m_programConfig
->writeEntry(ProgramArgs
, m_programArgs
);
589 m_programConfig
->writeEntry(WorkingDirectory
, m_programWD
);
590 m_programConfig
->writeEntry(DebuggerCmdStr
, m_debuggerCmd
);
591 m_programConfig
->writeEntry(TTYLevelEntry
, int(m_ttyLevel
));
593 // write environment variables
594 m_programConfig
->deleteGroup(EnvironmentGroup
);
595 m_programConfig
->setGroup(EnvironmentGroup
);
596 QDictIterator
<EnvVar
> it
= m_envVars
;
600 for (int i
= 0; (var
= it
) != 0; ++it
, ++i
) {
601 varName
.sprintf(Variable
, i
);
602 varValue
.sprintf(Value
, i
);
603 m_programConfig
->writeEntry(varName
, it
.currentKey());
604 m_programConfig
->writeEntry(varValue
, var
->value
);
607 saveBreakpoints(m_programConfig
);
610 // first get rid of whatever was in this group
611 m_programConfig
->deleteGroup(WatchGroup
);
612 // then start a new group
613 m_programConfig
->setGroup(WatchGroup
);
614 KTreeViewItem
* item
= m_watchVariables
.itemAt(0);
616 for (; item
!= 0; item
= item
->getSibling(), ++watchNum
) {
617 varName
.sprintf(ExprFmt
, watchNum
);
618 m_programConfig
->writeEntry(varName
, item
->getText());
621 // give others a chance
622 emit
saveProgramSpecific(m_programConfig
);
625 void KDebugger::restoreProgramSettings()
627 ASSERT(m_programConfig
!= 0);
628 m_programConfig
->setGroup(GeneralGroup
);
630 * We ignore file version for now we will use it in the future to
631 * distinguish different versions of this configuration file.
633 m_debuggerCmd
= m_programConfig
->readEntry(DebuggerCmdStr
);
634 // m_ttyLevel has been read in already
635 QString pgmArgs
= m_programConfig
->readEntry(ProgramArgs
);
636 QString pgmWd
= m_programConfig
->readEntry(WorkingDirectory
);
638 // read environment variables
639 m_programConfig
->setGroup(EnvironmentGroup
);
641 QDict
<EnvVar
> pgmVars
;
645 for (int i
= 0;; ++i
) {
646 varName
.sprintf(Variable
, i
);
647 varValue
.sprintf(Value
, i
);
648 if (!m_programConfig
->hasKey(varName
)) {
649 /* entry not present, assume that we've hit them all */
652 QString name
= m_programConfig
->readEntry(varName
);
653 if (name
.isEmpty()) {
658 var
->value
= m_programConfig
->readEntry(varValue
);
659 var
->status
= EnvVar::EVnew
;
660 pgmVars
.insert(name
, var
);
663 updateProgEnvironment(pgmArgs
, pgmWd
, pgmVars
);
665 restoreBreakpoints(m_programConfig
);
668 m_programConfig
->setGroup(WatchGroup
);
669 m_watchVariables
.clear();
670 for (int i
= 0;; ++i
) {
671 varName
.sprintf(ExprFmt
, i
);
672 if (!m_programConfig
->hasKey(varName
)) {
673 /* entry not present, assume that we've hit them all */
676 QString expr
= m_programConfig
->readEntry(varName
);
677 if (expr
.isEmpty()) {
678 // skip empty expressions
684 // give others a chance
685 emit
restoreProgramSpecific(m_programConfig
);
689 * Breakpoints are saved one per group.
691 const char BPGroup
[] = "Breakpoint %d";
692 const char File
[] = "File";
693 const char Line
[] = "Line";
694 const char Address
[] = "Address";
695 const char Temporary
[] = "Temporary";
696 const char Enabled
[] = "Enabled";
697 const char Condition
[] = "Condition";
699 void KDebugger::saveBreakpoints(KSimpleConfig
* config
)
703 for (uint j
= 0; j
< m_brkpts
.size(); j
++) {
704 Breakpoint
* bp
= m_brkpts
[j
];
705 if (bp
->type
== Breakpoint::watchpoint
)
706 continue; /* don't save watchpoints */
707 groupName
.sprintf(BPGroup
, i
++);
708 config
->setGroup(groupName
);
709 if (!bp
->fileName
.isEmpty()) {
710 config
->writeEntry(File
, bp
->fileName
);
711 config
->writeEntry(Line
, bp
->lineNo
);
713 * Addresses are hardly correct across sessions, so we remove
714 * it since we have a file name and line number.
716 config
->deleteEntry(Address
, false);
718 config
->writeEntry(Address
, bp
->address
.asString());
719 /* remove remmants */
720 config
->deleteEntry(File
, false);
721 config
->deleteEntry(Line
, false);
723 config
->writeEntry(Temporary
, bp
->temporary
);
724 config
->writeEntry(Enabled
, bp
->enabled
);
725 if (bp
->condition
.isEmpty())
726 config
->deleteEntry(Condition
, false);
728 config
->writeEntry(Condition
, bp
->condition
);
729 // we do not save the ignore count
731 // delete remaining groups
732 // we recognize that a group is present if there is an Enabled entry
734 groupName
.sprintf(BPGroup
, i
);
735 config
->setGroup(groupName
);
736 if (!config
->hasKey(Enabled
)) {
737 /* group not present, assume that we've hit them all */
740 config
->deleteGroup(groupName
);
744 void KDebugger::restoreBreakpoints(KSimpleConfig
* config
)
750 bool enabled
, temporary
;
753 * We recognize the end of the list if there is no Enabled entry
756 for (int i
= 0;; i
++) {
757 groupName
.sprintf(BPGroup
, i
);
758 config
->setGroup(groupName
);
759 if (!config
->hasKey(Enabled
)) {
760 /* group not present, assume that we've hit them all */
763 fileName
= config
->readEntry(File
);
764 lineNo
= config
->readNumEntry(Line
, -1);
765 address
= config
->readEntry(Address
);
766 if ((fileName
.isEmpty() || lineNo
< 0) && address
.isEmpty())
768 enabled
= config
->readBoolEntry(Enabled
, true);
769 temporary
= config
->readBoolEntry(Temporary
, false);
770 condition
= config
->readEntry(Condition
);
772 * Add the breakpoint. We assume that we have started a new
773 * instance of gdb, because we assign the breakpoint ids ourselves,
774 * starting with 1. Then we use this id to disable the breakpoint,
775 * if necessary. If this assignment of ids doesn't work, (maybe
776 * because this isn't a fresh gdb at all), we disable the wrong
777 * breakpoint! Oh well... for now it works.
779 if (!fileName
.isEmpty()) {
780 m_d
->executeCmd(temporary
? DCtbreakline
: DCbreakline
,
783 m_d
->executeCmd(temporary
? DCtbreakaddr
: DCbreakaddr
,
787 m_d
->executeCmd(DCdisable
, i
+1);
789 if (!condition
.isEmpty()) {
790 m_d
->executeCmd(DCcondition
, condition
, i
+1);
793 m_d
->queueCmd(DCinfobreak
, DebuggerDriver::QMoverride
);
797 // parse output of command cmd
798 void KDebugger::parse(CmdQueueItem
* cmd
, const char* output
)
800 ASSERT(cmd
!= 0); /* queue mustn't be empty */
802 TRACE(QString(__PRETTY_FUNCTION__
) + " parsing " + output
);
804 switch (cmd
->m_cmd
) {
806 // the output (if any) is uninteresting
809 // there is no output
812 /* if value is empty, we see output, but we don't care */
815 /* display gdb's message in the status bar */
816 m_d
->parseChangeWD(output
, m_statusMessage
);
817 emit
updateStatusMessage();
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
);
836 if (!m_statusMessage
.isEmpty())
837 emit
updateStatusMessage();
839 QString msg
= "gdb: " + m_statusMessage
;
841 KMsgBox::message(parentWidget(), kapp
->appName(), msg
,
842 KMsgBox::STOP
, i18n("OK"));
844 KMessageBox::sorry(parentWidget(), msg
);
847 m_corefile
= ""; /* don't process core file */
848 m_haveExecutable
= false;
852 // in any event we have an executable at this point
853 m_haveExecutable
= true;
854 if (m_d
->parseCoreFile(output
)) {
855 // loading a core is like stopping at a breakpoint
856 m_programActive
= true;
857 handleRunCommands(output
);
858 // do not reset m_corefile
861 QString msg
= m_d
->driverName() + ": " + QString(output
);
863 KMsgBox::message(parentWidget(), kapp
->appName(), msg
,
864 KMsgBox::EXCLAMATION
, i18n("OK"));
866 KMessageBox::sorry(parentWidget(), msg
);
868 // if core file was loaded from command line, revert to info line main
869 if (!cmd
->m_byUser
) {
870 m_d
->queueCmd(DCinfolinemain
, DebuggerDriver::QMnormal
);
872 m_corefile
= QString(); /* core file not available any more */
876 // ignore the output, marked file info follows
877 m_haveExecutable
= true;
880 // parse local variables
881 if (output
[0] != '\0') {
882 handleLocals(output
);
885 case DCinforegisters
:
886 handleRegisters(output
);
889 handleMemoryDump(output
);
892 handleInfoLine(cmd
, output
);
895 handleDisassemble(cmd
, output
);
898 handleFrameChange(output
);
902 handleBacktrace(output
);
906 handlePrint(cmd
, output
);
918 handleRunCommands(output
);
921 m_programRunning
= m_programActive
= false;
923 emit
updatePC(QString(), -1, DbgAddr(), 0);
931 newBreakpoint(output
);
936 // these commands need immediate response
937 m_d
->queueCmd(DCinfobreak
, DebuggerDriver::QMoverrideMoreEqual
);
940 // note: this handler must not enqueue a command, since
941 // DCinfobreak is used at various different places.
942 updateBreakList(output
);
943 emit
lineItemsChanged();
946 handleFindType(cmd
, output
);
949 case DCprintQStringStruct
:
950 handlePrintStruct(cmd
, output
);
952 case DCinfosharedlib
:
953 handleSharedLibs(output
);
957 // we are not interested in the output
960 handleThreadList(output
);
965 void KDebugger::backgroundUpdate()
968 * If there are still expressions that need to be updated, then do so.
974 void KDebugger::handleRunCommands(const char* output
)
976 uint flags
= m_d
->parseProgramStopped(output
, m_statusMessage
);
977 emit
updateStatusMessage();
979 m_programActive
= flags
& DebuggerDriver::SFprogramActive
;
981 // refresh files if necessary
982 if (flags
& DebuggerDriver::SFrefreshSource
) {
983 TRACE("re-reading files");
984 emit
executableUpdated();
988 * If we stopped at a breakpoint, we must update the breakpoint list
989 * because the hit count changes. Also, if the breakpoint was temporary
990 * it would go away now.
992 if ((flags
& (DebuggerDriver::SFrefreshBreak
|DebuggerDriver::SFrefreshSource
)) ||
993 stopMayChangeBreakList())
995 m_d
->queueCmd(DCinfobreak
, DebuggerDriver::QMoverride
);
999 * If we haven't listed the shared libraries yet, do so. We must do
1000 * this before we emit any commands that list variables, since the type
1001 * libraries depend on the shared libraries.
1003 if (!m_sharedLibsListed
) {
1004 // must be a high-priority command!
1005 m_d
->executeCmd(DCinfosharedlib
);
1008 // get the backtrace if the program is running
1009 if (m_programActive
) {
1010 m_d
->queueCmd(DCbt
, DebuggerDriver::QMoverride
);
1012 // program finished: erase PC
1013 emit
updatePC(QString(), -1, DbgAddr(), 0);
1014 // dequeue any commands in the queues
1015 m_d
->flushCommands();
1018 /* Update threads list */
1019 if (flags
& DebuggerDriver::SFrefreshThreads
) {
1020 m_d
->queueCmd(DCinfothreads
, DebuggerDriver::QMoverride
);
1023 m_programRunning
= false;
1024 emit
programStopped();
1027 void KDebugger::slotInferiorRunning()
1029 m_programRunning
= true;
1032 void KDebugger::updateAllExprs()
1034 if (!m_programActive
)
1037 // retrieve local variables
1038 m_d
->queueCmd(DCinfolocals
, DebuggerDriver::QMoverride
);
1040 // retrieve registers
1041 m_d
->queueCmd(DCinforegisters
, DebuggerDriver::QMoverride
);
1043 // get new memory dump
1044 if (!m_memoryExpression
.isEmpty()) {
1045 queueMemoryDump(false);
1048 // update watch expressions
1049 KTreeViewItem
* item
= m_watchVariables
.itemAt(0);
1050 for (; item
!= 0; item
= item
->getSibling()) {
1051 m_watchEvalExpr
.append(static_cast<VarTree
*>(item
));
1055 void KDebugger::updateProgEnvironment(const QString
& args
, const QString
& wd
,
1056 const QDict
<EnvVar
>& newVars
)
1058 m_programArgs
= args
;
1059 m_d
->executeCmd(DCsetargs
, m_programArgs
);
1060 TRACE("new pgm args: " + m_programArgs
+ "\n");
1062 m_programWD
= wd
.stripWhiteSpace();
1063 if (!m_programWD
.isEmpty()) {
1064 m_d
->executeCmd(DCcd
, m_programWD
);
1065 TRACE("new wd: " + m_programWD
+ "\n");
1068 QDictIterator
<EnvVar
> it
= newVars
;
1070 for (; (val
= it
) != 0; ++it
) {
1071 QString var
= it
.currentKey();
1072 switch (val
->status
) {
1074 m_envVars
.insert(var
, val
);
1076 case EnvVar::EVdirty
:
1077 // the value must be in our list
1078 ASSERT(m_envVars
[var
] == val
);
1080 m_d
->executeCmd(DCsetenv
, var
, val
->value
);
1082 case EnvVar::EVdeleted
:
1083 // must be in our list
1084 ASSERT(m_envVars
[var
] == val
);
1086 m_d
->executeCmd(DCunsetenv
, var
);
1087 m_envVars
.remove(var
);
1091 case EnvVar::EVclean
:
1092 // variable not changed
1098 void KDebugger::handleLocals(const char* output
)
1100 // retrieve old list of local variables
1102 m_localVariables
.exprList(oldVars
);
1105 * Get local variables.
1107 QList
<VarTree
> newVars
;
1108 parseLocals(output
, newVars
);
1111 * Clear any old VarTree item pointers, so that later we don't access
1112 * dangling pointers.
1114 m_localVariables
.clearPendingUpdates();
1117 bool autoU
= m_localVariables
.autoUpdate();
1118 m_localVariables
.setAutoUpdate(false);
1119 bool repaintNeeded
= false;
1122 * Match old variables against new ones.
1124 for (const char* n
= oldVars
.first(); n
!= 0; n
= oldVars
.next()) {
1125 // lookup this variable in the list of new variables
1126 VarTree
* v
= newVars
.first();
1127 while (v
!= 0 && strcmp(v
->getText(), n
) != 0) {
1131 // old variable not in the new variables
1132 TRACE(QString("old var deleted: ") + n
);
1133 v
= m_localVariables
.topLevelExprByName(n
);
1134 removeExpr(&m_localVariables
, v
);
1135 if (v
!= 0) repaintNeeded
= true;
1137 // variable in both old and new lists: update
1138 TRACE(QString("update var: ") + n
);
1139 m_localVariables
.updateExpr(newVars
.current());
1140 // remove the new variable from the list
1143 #if QT_VERSION >= 200
1144 repaintNeeded
= true;
1148 // insert all remaining new variables
1149 for (VarTree
* v
= newVars
.first(); v
!= 0; v
= newVars
.next()) {
1150 TRACE("new var: " + v
->getText());
1151 m_localVariables
.insertExpr(v
);
1152 repaintNeeded
= true;
1156 m_localVariables
.setAutoUpdate(autoU
);
1157 if (repaintNeeded
&& autoU
&& m_localVariables
.isVisible())
1158 m_localVariables
.repaint();
1161 void KDebugger::parseLocals(const char* output
, QList
<VarTree
>& newVars
)
1163 QList
<VarTree
> vars
;
1164 m_d
->parseLocals(output
, vars
);
1166 QString origName
; /* used in renaming variables */
1167 while (vars
.count() > 0)
1169 VarTree
* variable
= vars
.take(0);
1171 variable
->inferTypesOfChildren(*m_typeTable
);
1173 * When gdb prints local variables, those from the innermost block
1174 * come first. We run through the list of already parsed variables
1175 * to find duplicates (ie. variables that hide local variables from
1176 * a surrounding block). We keep the name of the inner variable, but
1177 * rename those from the outer block so that, when the value is
1178 * updated in the window, the value of the variable that is
1179 * _visible_ changes the color!
1182 origName
= variable
->getText();
1183 for (VarTree
* v
= newVars
.first(); v
!= 0; v
= newVars
.next()) {
1184 if (variable
->getText() == v
->getText()) {
1185 // we found a duplicate, change name
1187 QString newName
= origName
+ " (" + QString().setNum(block
) + ")";
1188 variable
->setText(newName
);
1191 newVars
.append(variable
);
1195 bool KDebugger::handlePrint(CmdQueueItem
* cmd
, const char* output
)
1197 ASSERT(cmd
->m_expr
!= 0);
1199 VarTree
* variable
= parseExpr(output
, true);
1203 // set expression "name"
1204 variable
->setText(cmd
->m_expr
->getText());
1206 if (cmd
->m_expr
->m_varKind
== VarTree::VKpointer
) {
1208 * We must insert a dummy parent, because otherwise variable's value
1209 * would overwrite cmd->m_expr's value.
1211 VarTree
* dummyParent
= new VarTree(variable
->getText(), VarTree::NKplain
);
1212 dummyParent
->m_varKind
= VarTree::VKdummy
;
1213 // the name of the parsed variable is the address of the pointer
1214 QString addr
= "*" + cmd
->m_expr
->m_value
;
1215 variable
->setText(addr
);
1216 variable
->m_nameKind
= VarTree::NKaddress
;
1218 dummyParent
->appendChild(variable
);
1219 dummyParent
->setDeleteChildren(true);
1220 TRACE("update ptr: " + cmd
->m_expr
->getText());
1221 cmd
->m_exprWnd
->updateExpr(cmd
->m_expr
, dummyParent
);
1224 TRACE("update expr: " + cmd
->m_expr
->getText());
1225 cmd
->m_exprWnd
->updateExpr(cmd
->m_expr
, variable
);
1229 evalExpressions(); /* enqueue dereferenced pointers */
1234 VarTree
* KDebugger::parseExpr(const char* output
, bool wantErrorValue
)
1238 // check for error conditions
1239 bool goodValue
= m_d
->parsePrintExpr(output
, wantErrorValue
, variable
);
1241 if (variable
!= 0 && goodValue
)
1244 variable
->inferTypesOfChildren(*m_typeTable
);
1249 // parse the output of bt
1250 void KDebugger::handleBacktrace(const char* output
)
1253 m_btWindow
.setAutoUpdate(false);
1257 QList
<StackFrame
> stack
;
1258 m_d
->parseBackTrace(output
, stack
);
1260 if (stack
.count() > 0) {
1261 StackFrame
* frm
= stack
.take(0);
1262 // first frame must set PC
1263 // note: frm->lineNo is zero-based
1264 emit
updatePC(frm
->fileName
, frm
->lineNo
, frm
->address
, frm
->frameNo
);
1269 func
= frm
->var
->getText();
1271 func
= frm
->fileName
+ ":" + QString().setNum(frm
->lineNo
+1);
1272 m_btWindow
.insertItem(func
);
1273 TRACE("frame " + func
+ " (" + frm
->fileName
+ ":" +
1274 QString().setNum(frm
->lineNo
+1) + ")");
1277 while ((frm
= stack
.take()) != 0);
1280 m_btWindow
.setAutoUpdate(true);
1281 m_btWindow
.repaint();
1284 void KDebugger::gotoFrame(int frame
)
1286 m_d
->executeCmd(DCframe
, frame
);
1289 void KDebugger::handleFrameChange(const char* output
)
1295 if (m_d
->parseFrameChange(output
, frameNo
, fileName
, lineNo
, address
)) {
1296 /* lineNo can be negative here if we can't find a file name */
1297 emit
updatePC(fileName
, lineNo
, address
, frameNo
);
1299 emit
updatePC(fileName
, -1, address
, frameNo
);
1303 void KDebugger::evalExpressions()
1305 // evaluate expressions in the following order:
1306 // watch expressions
1307 // pointers in local variables
1308 // pointers in watch expressions
1309 // types in local variables
1310 // types in watch expressions
1311 // pointers in 'this'
1314 VarTree
* exprItem
= m_watchEvalExpr
.first();
1315 if (exprItem
!= 0) {
1316 m_watchEvalExpr
.remove();
1317 QString expr
= exprItem
->computeExpr();
1318 TRACE("watch expr: " + expr
);
1319 CmdQueueItem
* cmd
= m_d
->queueCmd(DCprint
, expr
, DebuggerDriver::QMoverride
);
1320 // remember which expr this was
1321 cmd
->m_expr
= exprItem
;
1322 cmd
->m_exprWnd
= &m_watchVariables
;
1326 #define POINTER(widget) \
1328 exprItem = widget.nextUpdatePtr(); \
1329 if (exprItem != 0) goto pointer
1330 #define STRUCT(widget) \
1332 exprItem = widget.nextUpdateStruct(); \
1333 if (exprItem != 0) goto ustruct
1334 #define TYPE(widget) \
1336 exprItem = widget.nextUpdateType(); \
1337 if (exprItem != 0) goto type
1339 POINTER(m_localVariables
);
1340 POINTER(m_watchVariables
);
1341 STRUCT(m_localVariables
);
1342 STRUCT(m_watchVariables
);
1343 TYPE(m_localVariables
);
1344 TYPE(m_watchVariables
);
1351 // we have an expression to send
1352 dereferencePointer(wnd
, exprItem
, false);
1357 if (exprItem
->m_type
== 0 || exprItem
->m_type
== TypeInfo::unknownType())
1359 evalInitialStructExpression(exprItem
, wnd
, false);
1364 * Sometimes a VarTree gets registered twice for a type update. So
1365 * it may happen that it has already been updated. Hence, we ignore
1366 * it here and go on to the next task.
1368 if (exprItem
->m_type
!= 0)
1370 determineType(wnd
, exprItem
);
1374 void KDebugger::dereferencePointer(ExprWnd
* wnd
, VarTree
* exprItem
,
1377 ASSERT(exprItem
->m_varKind
== VarTree::VKpointer
);
1379 QString expr
= exprItem
->computeExpr();
1380 TRACE("dereferencing pointer: " + expr
);
1381 QString queueExpr
= "*(" + expr
+ ")";
1384 cmd
= m_d
->queueCmd(DCprint
, queueExpr
, DebuggerDriver::QMoverrideMoreEqual
);
1386 cmd
= m_d
->queueCmd(DCprint
, queueExpr
, DebuggerDriver::QMoverride
);
1388 // remember which expr this was
1389 cmd
->m_expr
= exprItem
;
1390 cmd
->m_exprWnd
= wnd
;
1393 void KDebugger::determineType(ExprWnd
* wnd
, VarTree
* exprItem
)
1395 ASSERT(exprItem
->m_varKind
== VarTree::VKstruct
);
1397 QString expr
= exprItem
->computeExpr();
1398 TRACE("get type of: " + expr
);
1400 cmd
= m_d
->queueCmd(DCfindType
, expr
, DebuggerDriver::QMoverride
);
1402 // remember which expr this was
1403 cmd
->m_expr
= exprItem
;
1404 cmd
->m_exprWnd
= wnd
;
1407 void KDebugger::handleFindType(CmdQueueItem
* cmd
, const char* output
)
1410 if (m_d
->parseFindType(output
, type
))
1412 ASSERT(cmd
!= 0 && cmd
->m_expr
!= 0);
1414 TypeInfo
* info
= m_typeTable
->lookup(type
);
1418 * We've asked gdb for the type of the expression in
1419 * cmd->m_expr, but it returned a name we don't know. The base
1420 * class (and member) types have been checked already (at the
1421 * time when we parsed that particular expression). Now it's
1422 * time to derive the type from the base classes as a last
1425 info
= cmd
->m_expr
->inferTypeFromBaseClass();
1426 // if we found a type through this method, register an alias
1428 TRACE("infered alias: " + type
);
1429 m_typeTable
->registerAlias(type
, info
);
1433 TRACE("unknown type");
1434 cmd
->m_expr
->m_type
= TypeInfo::unknownType();
1436 cmd
->m_expr
->m_type
= info
;
1437 /* since this node has a new type, we get its value immediately */
1438 evalInitialStructExpression(cmd
->m_expr
, cmd
->m_exprWnd
, false);
1443 evalExpressions(); /* queue more of them */
1446 void KDebugger::handlePrintStruct(CmdQueueItem
* cmd
, const char* output
)
1448 VarTree
* var
= cmd
->m_expr
;
1450 ASSERT(var
->m_varKind
== VarTree::VKstruct
);
1453 if (cmd
->m_cmd
!= DCprintQStringStruct
) {
1454 partExpr
= parseExpr(output
, false);
1456 partExpr
= m_d
->parseQCharArray(output
, false, m_typeTable
->qCharIsShort());
1460 /* we only allow simple values at the moment */
1461 partExpr
->childCount() != 0;
1466 partValue
= "?""?""?"; // 2 question marks in a row would be a trigraph
1468 partValue
= partExpr
->m_value
;
1474 * Updating a struct value works like this: var->m_partialValue holds
1475 * the value that we have gathered so far (it's been initialized with
1476 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1477 * we append the printed result followed by the next
1478 * var->m_type->m_displayString to var->m_partialValue.
1480 * If the expression we just evaluated was a guard expression, and it
1481 * resulted in an error, we must not evaluate the real expression, but
1482 * go on to the next index. (We must still add the question marks to
1485 * Next, if this was the length expression, we still have not seen the
1486 * real expression, but the length of a QString.
1488 ASSERT(var
->m_exprIndex
>= 0 && var
->m_exprIndex
<= typeInfoMaxExpr
);
1490 if (errorValue
|| !var
->m_exprIndexUseGuard
)
1492 // add current partValue (which might be the question marks)
1493 #if QT_VERSION < 200
1494 var
->m_partialValue
.detach();
1496 var
->m_partialValue
+= partValue
;
1497 var
->m_exprIndex
++; /* next part */
1498 var
->m_exprIndexUseGuard
= true;
1499 var
->m_partialValue
+= var
->m_type
->m_displayString
[var
->m_exprIndex
];
1503 // this was a guard expression that succeeded
1504 // go for the real expression
1505 var
->m_exprIndexUseGuard
= false;
1508 /* go for more sub-expressions if needed */
1509 if (var
->m_exprIndex
< var
->m_type
->m_numExprs
) {
1510 /* queue a new print command with quite high priority */
1511 evalStructExpression(var
, cmd
->m_exprWnd
, true);
1515 cmd
->m_exprWnd
->updateStructValue(var
);
1517 evalExpressions(); /* enqueue dereferenced pointers */
1520 /* queues the first printStruct command for a struct */
1521 void KDebugger::evalInitialStructExpression(VarTree
* var
, ExprWnd
* wnd
, bool immediate
)
1523 var
->m_exprIndex
= 0;
1524 var
->m_exprIndexUseGuard
= true;
1525 var
->m_partialValue
= var
->m_type
->m_displayString
[0];
1526 evalStructExpression(var
, wnd
, immediate
);
1529 /* queues a printStruct command; var must have been initialized correctly */
1530 void KDebugger::evalStructExpression(VarTree
* var
, ExprWnd
* wnd
, bool immediate
)
1532 QString base
= var
->computeExpr();
1534 if (var
->m_exprIndexUseGuard
) {
1535 exprFmt
= var
->m_type
->m_guardStrings
[var
->m_exprIndex
];
1536 if (exprFmt
.isEmpty()) {
1537 // no guard, omit it and go to expression
1538 var
->m_exprIndexUseGuard
= false;
1541 if (!var
->m_exprIndexUseGuard
) {
1542 exprFmt
= var
->m_type
->m_exprStrings
[var
->m_exprIndex
];
1545 SIZED_QString(expr
, exprFmt
.length() + base
.length() + 10);
1546 expr
.sprintf(exprFmt
, base
.data());
1548 DbgCommand dbgCmd
= DCprintStruct
;
1549 // check if this is a QString::Data
1550 if (strncmp(expr
, "/QString::Data ", 15) == 0)
1552 if (m_typeTable
->parseQt2QStrings())
1554 expr
= expr
.mid(15, expr
.length()); /* strip off /QString::Data */
1555 dbgCmd
= DCprintQStringStruct
;
1558 * This should not happen: the type libraries should be set up
1559 * in a way that this can't happen. If this happens
1560 * nevertheless it means that, eg., kdecore was loaded but qt2
1561 * was not (only qt2 enables the QString feature).
1563 // TODO: remove this "print"; queue the next printStruct instead
1569 TRACE("evalStruct: " + expr
+ (var
->m_exprIndexUseGuard
? " // guard" : " // real"));
1570 CmdQueueItem
* cmd
= m_d
->queueCmd(dbgCmd
, expr
,
1571 immediate
? DebuggerDriver::QMoverrideMoreEqual
1572 : DebuggerDriver::QMnormal
);
1574 // remember which expression this was
1576 cmd
->m_exprWnd
= wnd
;
1579 /* removes expression from window */
1580 void KDebugger::removeExpr(ExprWnd
* wnd
, VarTree
* var
)
1585 // must remove any references to var from command queues
1586 m_d
->dequeueCmdByVar(var
);
1588 wnd
->removeExpr(var
);
1591 void KDebugger::handleSharedLibs(const char* output
)
1593 // delete all known libraries
1594 m_sharedLibs
.clear();
1596 // parse the table of shared libraries
1597 m_d
->parseSharedLibs(output
, m_sharedLibs
);
1598 m_sharedLibsListed
= true;
1600 // get type libraries
1601 m_typeTable
->loadLibTypes(m_sharedLibs
);
1604 CmdQueueItem
* KDebugger::loadCoreFile()
1606 return m_d
->queueCmd(DCcorefile
, m_corefile
, DebuggerDriver::QMoverride
);
1609 void KDebugger::slotLocalsExpanding(KTreeViewItem
* item
, bool& allow
)
1611 exprExpandingHelper(&m_localVariables
, item
, allow
);
1614 void KDebugger::slotWatchExpanding(KTreeViewItem
* item
, bool& allow
)
1616 exprExpandingHelper(&m_watchVariables
, item
, allow
);
1619 void KDebugger::exprExpandingHelper(ExprWnd
* wnd
, KTreeViewItem
* item
, bool&)
1621 VarTree
* exprItem
= static_cast<VarTree
*>(item
);
1622 if (exprItem
->m_varKind
!= VarTree::VKpointer
) {
1625 dereferencePointer(wnd
, exprItem
, true);
1628 // add the expression in the edit field to the watch expressions
1629 void KDebugger::addWatch(const QString
& t
)
1631 QString expr
= t
.stripWhiteSpace();
1634 VarTree
* exprItem
= new VarTree(expr
, VarTree::NKplain
);
1635 m_watchVariables
.insertExpr(exprItem
);
1637 // if we are boring ourselves, send down the command
1638 if (m_programActive
) {
1639 m_watchEvalExpr
.append(exprItem
);
1640 if (m_d
->isIdle()) {
1646 // delete a toplevel watch expression
1647 void KDebugger::slotDeleteWatch()
1649 // delete only allowed while debugger is idle; or else we might delete
1650 // the very expression the debugger is currently working on...
1654 int index
= m_watchVariables
.currentItem();
1658 VarTree
* item
= static_cast<VarTree
*>(m_watchVariables
.itemAt(index
));
1659 if (!item
->isToplevelExpr())
1662 // remove the variable from the list to evaluate
1663 if (m_watchEvalExpr
.findRef(item
) >= 0) {
1664 m_watchEvalExpr
.remove();
1666 removeExpr(&m_watchVariables
, item
);
1667 // item is invalid at this point!
1670 void KDebugger::startAnimation(bool fast
)
1672 int interval
= fast
? 50 : 150;
1673 if (!m_animationTimer
.isActive()) {
1674 m_animationTimer
.start(interval
);
1675 } else if (m_animationInterval
!= interval
) {
1676 m_animationTimer
.changeInterval(interval
);
1678 m_animationInterval
= interval
;
1681 void KDebugger::stopAnimation()
1683 if (m_animationTimer
.isActive()) {
1684 m_animationTimer
.stop();
1685 m_animationInterval
= 0;
1689 void KDebugger::slotUpdateAnimation()
1691 if (m_d
->isIdle()) {
1695 * Slow animation while program is stopped (i.e. while variables
1698 bool slow
= isReady() && m_programActive
&& !m_programRunning
;
1699 startAnimation(!slow
);
1703 void KDebugger::handleRegisters(const char* output
)
1705 QList
<RegisterInfo
> regs
;
1706 m_d
->parseRegisters(output
, regs
);
1708 emit
registersChanged(regs
);
1711 regs
.setAutoDelete(true);
1715 * The output of the DCbreak* commands has more accurate information about
1716 * the file and the line number.
1718 void KDebugger::newBreakpoint(const char* output
)
1723 if (!m_d
->parseBreakpoint(output
, id
, file
, lineNo
))
1727 for (int i
= m_brkpts
.size()-1; i
>= 0; i
--) {
1728 if (m_brkpts
[i
]->id
== id
) {
1730 m_brkpts
[i
]->fileName
= file
;
1731 m_brkpts
[i
]->lineNo
= lineNo
;
1736 Breakpoint
* bp
= new Breakpoint
;
1738 bp
->temporary
= false;
1741 bp
->ignoreCount
= 0;
1742 bp
->fileName
= file
;
1743 bp
->lineNo
= lineNo
;
1744 int n
= m_brkpts
.size();
1745 m_brkpts
.resize(n
+1);
1749 void KDebugger::updateBreakList(const char* output
)
1752 QList
<Breakpoint
> brks
;
1753 brks
.setAutoDelete(false);
1754 m_d
->parseBreakList(output
, brks
);
1756 // merge new information into existing breakpoints
1758 QArray
<Breakpoint
*> oldbrks
= m_brkpts
;
1760 // move parsed breakpoints into m_brkpts
1762 m_brkpts
.resize(brks
.count());
1764 for (Breakpoint
* bp
= brks
.first(); bp
!= 0; bp
= brks
.next())
1769 // go through all old breakpoints
1770 for (int i
= oldbrks
.size()-1; i
>= 0; i
--) {
1771 // is this one still alive?
1772 for (int j
= m_brkpts
.size()-1; j
>= 0; j
--)
1774 if (m_brkpts
[j
]->id
== oldbrks
[i
]->id
) {
1776 // keep accurate location
1777 m_brkpts
[j
]->fileName
= oldbrks
[i
]->fileName
;
1778 m_brkpts
[j
]->lineNo
= oldbrks
[i
]->lineNo
;
1784 // delete old breakpoints
1785 for (int i
= oldbrks
.size()-1; i
>= 0; i
--) {
1789 emit
breakpointsChanged();
1792 // look if there is at least one temporary breakpoint
1794 bool KDebugger::stopMayChangeBreakList() const
1796 for (int i
= m_brkpts
.size()-1; i
>= 0; i
--) {
1797 Breakpoint
* bp
= m_brkpts
[i
];
1798 if (bp
->temporary
|| bp
->type
== Breakpoint::watchpoint
)
1804 Breakpoint
* KDebugger::breakpointByFilePos(QString file
, int lineNo
,
1805 const DbgAddr
& address
)
1807 // look for exact file name match
1809 for (i
= m_brkpts
.size()-1; i
>= 0; i
--) {
1810 if (m_brkpts
[i
]->lineNo
== lineNo
&&
1811 m_brkpts
[i
]->fileName
== file
&&
1812 (address
.isEmpty() || m_brkpts
[i
]->address
== address
))
1817 // not found, so try basename
1818 // strip off directory part of file name
1819 int offset
= file
.findRev("/");
1820 #if QT_VERSION < 200
1823 file
.remove(0, offset
+1);
1825 for (i
= m_brkpts
.size()-1; i
>= 0; i
--) {
1826 // get base name of breakpoint's file
1827 QString basename
= m_brkpts
[i
]->fileName
;
1828 int offset
= basename
.findRev("/");
1830 #if QT_VERSION < 200
1833 basename
.remove(0, offset
+1);
1836 if (m_brkpts
[i
]->lineNo
== lineNo
&&
1838 (address
.isEmpty() || m_brkpts
[i
]->address
== address
))
1848 void KDebugger::slotValuePopup(const QString
& expr
)
1850 // search the local variables for a match
1851 VarTree
* v
= m_localVariables
.topLevelExprByName(expr
);
1853 // not found, check watch expressions
1854 v
= m_watchVariables
.topLevelExprByName(expr
);
1856 // nothing found; do nothing
1861 // construct the tip
1862 QString tip
= v
->getText() + " = ";
1863 if (!v
->m_value
.isEmpty())
1869 // no value: we use some hint
1870 switch (v
->m_varKind
) {
1871 case VarTree::VKstruct
:
1874 case VarTree::VKarray
:
1878 tip
+= "?""?""?"; // 2 question marks in a row would be a trigraph
1882 emit
valuePopup(tip
);
1885 void KDebugger::slotDisassemble(const QString
& fileName
, int lineNo
)
1887 CmdQueueItem
* cmd
= m_d
->queueCmd(DCinfoline
, fileName
, lineNo
,
1888 DebuggerDriver::QMoverrideMoreEqual
);
1889 cmd
->m_fileName
= fileName
;
1890 cmd
->m_lineNo
= lineNo
;
1893 void KDebugger::handleInfoLine(CmdQueueItem
* cmd
, const char* output
)
1895 QString addrFrom
, addrTo
;
1896 if (m_d
->parseInfoLine(output
, addrFrom
, addrTo
)) {
1897 // got the address range, now get the real code
1898 CmdQueueItem
* c
= m_d
->queueCmd(DCdisassemble
, addrFrom
, addrTo
,
1899 DebuggerDriver::QMoverrideMoreEqual
);
1900 c
->m_fileName
= cmd
->m_fileName
;
1901 c
->m_lineNo
= cmd
->m_lineNo
;
1904 QList
<DisassembledCode
> empty
;
1905 emit
disassembled(cmd
->m_fileName
, cmd
->m_lineNo
, empty
);
1909 void KDebugger::handleDisassemble(CmdQueueItem
* cmd
, const char* output
)
1911 QList
<DisassembledCode
> code
;
1912 code
.setAutoDelete(true);
1913 m_d
->parseDisassemble(output
, code
);
1914 emit
disassembled(cmd
->m_fileName
, cmd
->m_lineNo
, code
);
1917 void KDebugger::handleThreadList(const char* output
)
1919 QList
<ThreadInfo
> threads
;
1920 threads
.setAutoDelete(true);
1921 m_d
->parseThreadList(output
, threads
);
1922 emit
threadsChanged(threads
);
1925 void KDebugger::setThread(int id
)
1927 m_d
->queueCmd(DCthread
, id
, DebuggerDriver::QMoverrideMoreEqual
);
1930 void KDebugger::setMemoryExpression(const QString
& memexpr
)
1932 m_memoryExpression
= memexpr
;
1934 // queue the new expression
1935 if (!m_memoryExpression
.isEmpty() &&
1936 isProgramActive() &&
1937 !isProgramRunning())
1939 queueMemoryDump(true);
1943 void KDebugger::queueMemoryDump(bool immediate
)
1945 m_d
->queueCmd(DCexamine
, m_memoryExpression
, m_memoryFormat
,
1946 immediate
? DebuggerDriver::QMoverrideMoreEqual
:
1947 DebuggerDriver::QMoverride
);
1950 void KDebugger::handleMemoryDump(const char* output
)
1952 QList
<MemoryDump
> memdump
;
1953 memdump
.setAutoDelete(true);
1954 QString msg
= m_d
->parseMemoryDump(output
, memdump
);
1955 emit
memoryDumpChanged(msg
, memdump
);
1959 #include "debugger.moc"