00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "gdbcontroller.h"
00019
00020 #include "breakpoint.h"
00021 #include "framestackwidget.h"
00022 #include "gdbcommand.h"
00023 #include "stty.h"
00024 #include "variablewidget.h"
00025 #include "domutil.h"
00026
00027 #include <kapplication.h>
00028 #include <kconfig.h>
00029 #include <kdebug.h>
00030 #include <kglobal.h>
00031 #include <klocale.h>
00032 #include <kmessagebox.h>
00033 #include <kprocess.h>
00034
00035 #include <qdatetime.h>
00036 #include <qfileinfo.h>
00037 #include <qregexp.h>
00038 #include <qstring.h>
00039
00040 #include <iostream>
00041 #include <ctype.h>
00042 #include <stdlib.h>
00043 using namespace std;
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 namespace GDBDebugger
00121 {
00122
00123
00124 int debug_controllerExists = false;
00125
00126
00127 GDBController::GDBController(VariableTree *varTree, FramestackWidget *frameStack, QDomDocument &projectDom)
00128 : DbgController(),
00129 frameStack_(frameStack),
00130 varTree_(varTree),
00131 currentFrame_(0),
00132 viewedThread_(-1),
00133 gdbOutputLen_(0),
00134 gdbOutput_(new char[2048]),
00135 holdingZone_(),
00136 currentCmd_(0),
00137 tty_(0),
00138 badCore_(QString()),
00139 state_(s_dbgNotStarted|s_appNotStarted|s_silent),
00140 programHasExited_(false),
00141 backtraceDueToProgramStop_(false),
00142 dom(projectDom),
00143 config_breakOnLoadingLibrary_(true),
00144 config_forceBPSet_(true),
00145 config_displayStaticMembers_(false),
00146 config_asmDemangle_(true),
00147 config_dbgTerminal_(false),
00148 config_gdbPath_(),
00149 config_outputRadix_(10)
00150 {
00151 gdbSizeofBuf_ = sizeof(gdbOutput_);
00152
00153 configure();
00154 cmdList_.setAutoDelete(true);
00155
00156 Q_ASSERT(! debug_controllerExists);
00157 debug_controllerExists = true;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167 GDBController::~GDBController()
00168 {
00169 delete[] gdbOutput_;
00170 debug_controllerExists = false;
00171 }
00172
00173
00174
00175 void GDBController::configure()
00176 {
00177
00178 config_configGdbScript_ = DomUtil::readEntry(dom, "/kdevdebugger/general/configGdbScript").latin1();
00179 config_runShellScript_ = DomUtil::readEntry(dom, "/kdevdebugger/general/runShellScript").latin1();
00180 config_runGdbScript_ = DomUtil::readEntry(dom, "/kdevdebugger/general/runGdbScript").latin1();
00181
00182
00183 config_forceBPSet_ = DomUtil::readBoolEntry(dom, "/kdevdebugger/general/allowforcedbpset", true);
00184 config_dbgTerminal_ = DomUtil::readBoolEntry(dom, "/kdevdebugger/general/separatetty", false);
00185 config_gdbPath_ = DomUtil::readEntry(dom, "/kdevdebugger/general/gdbpath");
00186
00187 bool old_displayStatic = config_displayStaticMembers_;
00188 config_displayStaticMembers_ = DomUtil::readBoolEntry(dom, "/kdevdebugger/display/staticmembers",false);
00189
00190 bool old_asmDemangle = config_asmDemangle_;
00191 config_asmDemangle_ = DomUtil::readBoolEntry(dom, "/kdevdebugger/display/demanglenames",true);
00192
00193 bool old_breakOnLoadingLibrary_ = config_breakOnLoadingLibrary_;
00194 config_breakOnLoadingLibrary_ = DomUtil::readBoolEntry(dom, "/kdevdebugger/general/breakonloadinglibs",true);
00195
00196 int old_outputRadix = config_outputRadix_;
00197 config_outputRadix_ = DomUtil::readIntEntry(dom, "/kdevdebugger/display/outputradix", 10);
00198 varTree_->setRadix(config_outputRadix_);
00199
00200
00201 if (( old_displayStatic != config_displayStaticMembers_ ||
00202 old_asmDemangle != config_asmDemangle_ ||
00203 old_breakOnLoadingLibrary_ != config_breakOnLoadingLibrary_ ||
00204 old_outputRadix != config_outputRadix_) &&
00205 dbgProcess_)
00206 {
00207 bool restart = false;
00208 if (stateIsOn(s_appBusy))
00209 {
00210 setStateOn(s_silent);
00211 pauseApp();
00212 restart = true;
00213 }
00214
00215 if (old_displayStatic != config_displayStaticMembers_)
00216 {
00217 if (config_displayStaticMembers_)
00218 queueCmd(new GDBCommand("set print static-members on", NOTRUNCMD,
00219 NOTINFOCMD));
00220 else
00221 queueCmd(new GDBCommand("set print static-members off", NOTRUNCMD,
00222 NOTINFOCMD));
00223 }
00224 if (old_asmDemangle != config_asmDemangle_)
00225 {
00226 if (config_asmDemangle_)
00227 queueCmd(new GDBCommand("set print asm-demangle on", NOTRUNCMD,
00228 NOTINFOCMD));
00229 else
00230 queueCmd(new GDBCommand("set print asm-demangle off", NOTRUNCMD,
00231 NOTINFOCMD));
00232 }
00233
00234 if (old_breakOnLoadingLibrary_ != config_breakOnLoadingLibrary_)
00235 {
00236 if (config_breakOnLoadingLibrary_)
00237 queueCmd(new GDBCommand("set stop-on 1", NOTRUNCMD, NOTINFOCMD));
00238 else
00239 queueCmd(new GDBCommand("set stop-on 0", NOTRUNCMD, NOTINFOCMD));
00240 }
00241
00242 if (old_outputRadix != config_outputRadix_)
00243 {
00244 queueCmd(new GDBCommand(QCString().sprintf("set output-radix %d",
00245 config_outputRadix_), NOTRUNCMD, NOTINFOCMD));
00246
00247
00248
00249 varTree_->findWatch()->requestWatchVars();
00250 queueCmd(new GDBCommand("info args", NOTRUNCMD, INFOCMD, ARGS));
00251 queueCmd(new GDBCommand("info local", NOTRUNCMD, INFOCMD, LOCALS));
00252 }
00253
00254 if (!config_configGdbScript_.isEmpty())
00255 queueCmd(new GDBCommand("source " + config_configGdbScript_, NOTRUNCMD, NOTINFOCMD, 0));
00256
00257 if (restart)
00258 queueCmd(new GDBCommand("continue", RUNCMD, NOTINFOCMD, 0));
00259 }
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 void GDBController::queueCmd(DbgCommand *cmd, bool executeNext)
00271 {
00272
00273
00274 if (cmd->isARunCmd())
00275 removeInfoRequests();
00276
00277 if (executeNext)
00278 cmdList_.insert(0, cmd);
00279 else
00280 cmdList_.append (cmd);
00281
00282 executeCmd();
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292 void GDBController::executeCmd()
00293 {
00294 if (stateIsOn(s_dbgNotStarted|s_waitForWrite|s_appBusy|s_shuttingDown) || !dbgProcess_)
00295 return;
00296
00297 if (!currentCmd_)
00298 {
00299 if (cmdList_.isEmpty())
00300 return;
00301
00302 currentCmd_ = cmdList_.take(0);
00303 }
00304
00305 if (!currentCmd_->moreToSend())
00306 {
00307 if (currentCmd_->expectReply())
00308 return;
00309
00310 delete currentCmd_;
00311 if (cmdList_.isEmpty())
00312 {
00313 currentCmd_ = 0;
00314 return;
00315 }
00316
00317 currentCmd_ = cmdList_.take(0);
00318 }
00319
00320 Q_ASSERT(currentCmd_ && currentCmd_->moreToSend());
00321
00322 dbgProcess_->writeStdin(currentCmd_->cmdToSend().data(),
00323 currentCmd_->cmdLength());
00324 setStateOn(s_waitForWrite);
00325
00326 if (currentCmd_->isARunCmd())
00327 {
00328 setStateOn(s_appBusy);
00329 kdDebug(9012) << "App is busy" << endl;
00330 setStateOff(s_appNotStarted|s_programExited|s_silent);
00331 }
00332
00333 QString prettyCmd = currentCmd_->cmdToSend();
00334 prettyCmd.replace( QRegExp("set prompt \032.\n"), "" );
00335 prettyCmd = "(gdb) " + prettyCmd;
00336 emit gdbStdout( prettyCmd.latin1() );
00337
00338 if (!stateIsOn(s_silent))
00339 emit dbgStatus ("", state_);
00340 }
00341
00342
00343
00344 void GDBController::destroyCmds()
00345 {
00346 if (currentCmd_)
00347 {
00348 delete currentCmd_;
00349 currentCmd_ = 0;
00350 }
00351
00352 while (!cmdList_.isEmpty())
00353 delete cmdList_.take(0);
00354 }
00355
00356
00357
00358 void GDBController::removeInfoRequests()
00359 {
00360 int i = cmdList_.count();
00361 while (i)
00362 {
00363 i--;
00364 DbgCommand *cmd = cmdList_.at(i);
00365 if (cmd->isAnInfoCmd() || cmd->isARunCmd())
00366 delete cmdList_.take(i);
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375 void GDBController::pauseApp()
00376 {
00377 int i = cmdList_.count();
00378 while (i)
00379 {
00380 i--;
00381 DbgCommand *cmd = cmdList_.at(i);
00382 if ((stateIsOn(s_silent) && cmd->isAnInfoCmd()) || cmd->isARunCmd())
00383 delete cmdList_.take(i);
00384 }
00385
00386 if (dbgProcess_ && stateIsOn(s_appBusy))
00387 dbgProcess_->kill(SIGINT);
00388 }
00389
00390
00391
00392
00393
00394 void GDBController::actOnProgramPause(const QString &msg)
00395 {
00396
00397 if (stateIsOn(s_appBusy))
00398 {
00399 kdDebug(9012) << "App is paused" << endl;
00400 setStateOff(s_appBusy);
00401 if (stateIsOn(s_silent))
00402 return;
00403
00404 emit dbgStatus (msg, state_);
00405
00406
00407
00408 viewedThread_ = -1;
00409 currentFrame_ = 0;
00410 varTree_->setActiveFlag();
00411 backtraceDueToProgramStop_ = true;
00412
00413
00414 if (stateIsOn(s_viewThreads))
00415 queueCmd(new GDBCommand("info thread", NOTRUNCMD, INFOCMD, INFOTHREAD), true);
00416
00417 queueCmd(new GDBCommand("backtrace", NOTRUNCMD, INFOCMD, BACKTRACE), true);
00418 if (stateIsOn(s_viewLocals))
00419 {
00420 queueCmd(new GDBCommand("info args", NOTRUNCMD, INFOCMD, ARGS));
00421 queueCmd(new GDBCommand("info local", NOTRUNCMD, INFOCMD, LOCALS));
00422 }
00423
00424 varTree_->findWatch()->requestWatchVars();
00425 varTree_->findWatch()->setActive();
00426 emit acceptPendingBPs();
00427 }
00428 }
00429
00430
00431
00432
00433
00434
00435
00436 void GDBController::programNoApp(const QString &msg, bool msgBox)
00437 {
00438 state_ = (s_appNotStarted|s_programExited|(state_&(s_viewLocals|s_shuttingDown)));
00439 destroyCmds();
00440
00441
00442
00443 viewedThread_ = -1;
00444 currentFrame_ = 0;
00445 varTree_->setActiveFlag();
00446
00447
00448 varTree_->viewport()->setUpdatesEnabled(false);
00449 varTree_->trim();
00450 varTree_->viewport()->setUpdatesEnabled(true);
00451 varTree_->repaint();
00452
00453 frameStack_->clear();
00454
00455 if (msgBox)
00456 KMessageBox::error(0, i18n("gdb message:\n")+msg);
00457
00458 emit dbgStatus (msg, state_);
00459 }
00460
00461
00462
00463
00464 void GDBController::parseLine(char* buf)
00465 {
00466 Q_ASSERT(*buf != (char)BLOCK_START);
00467
00468
00469 if (!*buf)
00470 return;
00471
00472 if (strncmp(buf, "The program no longer exists", 28) == 0)
00473 {
00474 programNoApp(QString(buf), false);
00475 programHasExited_ = true;
00476 return;
00477 }
00478
00479 if (strncmp(buf, "Prog", 4) == 0)
00480 {
00481 if ((strncmp(buf, "Program exited", 14) == 0))
00482 {
00483 kdDebug(9012) << "Parsed (exit) <" << QString(buf) << ">" << endl;
00484 programNoApp(QString(buf), false);
00485 programHasExited_ = true;
00486 return;
00487 }
00488
00489 if (strncmp(buf, "Program terminated", 18) == 0)
00490 {
00491 if (stateIsOn(s_core))
00492 {
00493 KMessageBox::information(0, QString(buf));
00494
00495 actOnProgramPause(QString(buf));
00496 }
00497 else
00498 {
00499 programNoApp(QString(buf), false);
00500 }
00501
00502 programHasExited_ = true;
00503 return;
00504 }
00505
00506 if (strncmp(buf, "Program received signal", 23) == 0)
00507 {
00508
00509
00510
00511
00512 if (strstr(buf+23, "SIGINT") && stateIsOn(s_silent))
00513 return;
00514
00515
00516
00517
00518
00519
00520 KMessageBox::information(0, QString(buf));
00521 actOnProgramPause(QString(buf));
00522 return;
00523 }
00524
00525
00526
00527 actOnProgramPause(QString(buf));
00528 return;
00529 }
00530
00531 if (strncmp(buf, "Cann", 4) == 0)
00532 {
00533
00534
00535
00536
00537
00540 if ( strncmp(buf, "Cannot insert breakpoint", 24)==0)
00541 {
00542 if (programHasExited_)
00543 {
00544 setStateOn(s_silent);
00545 actOnProgramPause(QString());
00546 int BPNo = atoi(buf+25);
00547 if (BPNo)
00548 {
00549 emit unableToSetBPNow(BPNo);
00550 queueCmd(new GDBCommand(
00551 QCString().sprintf("delete %d", BPNo),
00552 NOTRUNCMD, NOTINFOCMD));
00553 queueCmd(new GDBCommand("info breakpoints", NOTRUNCMD,
00554 NOTINFOCMD, BPLIST));
00555 queueCmd(new GDBCommand("continue", RUNCMD, NOTINFOCMD, 0));
00556 }
00557
00558 return;
00559 }
00560
00561
00562
00563 return;
00564 }
00565
00566
00567
00568 if ( strncmp(buf, "Cannot find user-level thread for LWP", 37)==0)
00569 {
00570 programNoApp(QString(buf), false);
00571 programHasExited_ = true;
00572 return;
00573 }
00574
00575
00576 actOnProgramPause(QString(buf));
00577 return;
00578 }
00579
00580 if ( strncmp(buf, "[New Thread", 11)==0)
00581 {
00582 if (!stateIsOn(s_viewThreads))
00583 {
00584 setStateOn(s_viewThreads);
00585 queueCmd(new GDBCommand("info thread", NOTRUNCMD, INFOCMD, INFOTHREAD),
00586 true);
00587 }
00588 return;
00589 }
00590
00591
00592
00593 if (strncmp(buf, "Watc", 4) == 0)
00594 {
00595 if ((strncmp(buf, "Watchpoint", 10)==0) &&
00596 (strstr(buf, "deleted because the program has left the block")))
00597 {
00598 int BPNo = atoi(buf+11);
00599 if (BPNo)
00600 {
00601 queueCmd(new GDBCommand(QCString().sprintf("delete %d",BPNo),
00602 NOTRUNCMD, NOTINFOCMD));
00603 }
00604 actOnProgramPause(QString(buf));
00605 }
00606
00607 queueCmd(new GDBCommand("info breakpoints",
00608 NOTRUNCMD, NOTINFOCMD, BPLIST));
00609
00610
00611 return;
00612 }
00613
00614 if (strncmp(buf, "Brea", 4) == 0 ||
00615 strncmp(buf, "Hard", 4) == 0)
00616 {
00617
00618
00619
00620 queueCmd(new GDBCommand("info breakpoints",
00621 NOTRUNCMD, NOTINFOCMD, BPLIST));
00622
00623
00624 return;
00625 }
00626
00627 if (strncmp(buf, "Temp", 4) == 0)
00628 {
00629 if (strncmp(buf, "Temporarily disabling shared library breakpoints:", 49) == 0)
00630 {
00631 kdDebug(9012) << "Parsed (START_Temp)<" << buf << ">" << endl;
00632 return;
00633 }
00634
00635 actOnProgramPause(QString(buf));
00636 kdDebug(9012) << "Unparsed (START_Temp)<" << buf << ">" << endl;
00637 return;
00638 }
00639
00640 if (strncmp(buf, "Stop", 4) == 0)
00641 {
00642 if (strncmp(buf, "Stopped due to shared library event", 35) == 0)
00643 {
00644
00645
00646
00647
00648
00649
00650 kdDebug(9012) << "Parsed (sh.lib) <" << buf << ">" << endl;
00651 if (currentCmd_ && (currentCmd_->rawDbgCommand() == "run" ||
00652 currentCmd_->rawDbgCommand() == "continue"))
00653 {
00654 setStateOn(s_silent);
00655 setStateOff(s_appBusy);
00656 kdDebug(9012) << "App is paused (quietly)" << endl;
00657 emit acceptPendingBPs();
00658 queueCmd(new GDBCommand("continue", RUNCMD, NOTINFOCMD, 0));
00659 }
00660 else
00661 actOnProgramPause(QString(buf));
00662
00663 return;
00664 }
00665
00666
00667
00668 actOnProgramPause(QString(buf));
00669 kdDebug(9012) << "Unparsed (START_Stop)<" << buf << ">" << endl;
00670 return;
00671 }
00672
00673 if (strncmp(buf, "warn", 4) == 0)
00674 {
00675 if (strncmp(buf, "warning: core file may not match", 32) == 0 ||
00676 strncmp(buf, "warning: exec file is newer", 27) == 0)
00677 {
00678 badCore_ = QString(buf);
00679 }
00680 actOnProgramPause(QString());
00681 return;
00682 }
00683
00684 if (strncmp(buf, "Core", 4) == 0)
00685 {
00686 kdDebug(9012) << "Parsed (Core)<" << buf << ">" << endl;
00687 actOnProgramPause(buf);
00688 if (!badCore_.isEmpty() &&
00689 strncmp(buf, "Core was generated by", 21) == 0)
00690 KMessageBox::error( 0,
00691 i18n("gdb message:\n")+badCore_ + "\n" +
00692 QString(buf)+"\n\n"+
00693 i18n("The symbols gdb resolves may be suspect"),
00694 i18n("Mismatched Core File"));
00695
00696 return;
00697 }
00698
00699 if (strncmp(buf, "No symbol", 9) == 0 ||
00700 strncmp(buf, "Single", 6) == 0 ||
00701 strncmp(buf, "No source file named", 20) == 0 ||
00702 strncmp(buf, "[Switching to Thread", 20) == 0 ||
00703 strncmp(buf, "[Thread debugging using", 23) == 0 ||
00704 strncmp(buf, "Current language:", 17) == 0 ||
00705 strncmp(buf, "Error while mapping shared library sections:", 44) == 0 ||
00706 strncmp(buf, "Error while reading shared library symbols:", 43) == 0 ||
00707 *buf == ':' )
00708 {
00709
00710
00711
00712 return;
00713 }
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 if (isdigit(*buf))
00724 {
00725
00726 parseProgramLocation(buf);
00727
00728 return;
00729 }
00730
00731
00733 if (
00734 strstr(buf, "not in executable format:") ||
00735 strstr(buf, "No such file or directory.") ||
00736 strstr(buf, i18n("No such file or directory.").local8Bit())||
00737 strstr(buf, "is not a core dump:") ||
00738 strncmp(buf, "ptrace: No such process.", 24)==0 ||
00739 strncmp(buf, "ptrace: Operation not permitted.", 32)==0 ||
00740 strncmp(buf, "No executable file specified.", 29)==0)
00741 {
00742 programNoApp(QString(buf), true);
00743 kdDebug(9012) << "Bad file <" << buf << ">" << endl;
00744 return;
00745 }
00746
00747
00748
00749 if (stateIsOn(s_appBusy))
00750 {
00751 if ((strncmp(buf, "No ", 3)==0) && strstr(buf, "not meaningful"))
00752 {
00753 kdDebug(9012) << "Parsed (not meaningful)<" << buf << ">" << endl;
00754 actOnProgramPause(QString(buf));
00755 return;
00756 }
00757
00758 kdDebug(9012) << "Unparsed (default - busy)<" << buf << ">" << endl;
00759 actOnProgramPause(QString());
00760 return;
00761 }
00762
00763
00764 kdDebug(9012) << "Unparsed (default - not busy)<" << buf << ">" << endl;
00765 return;
00766 }
00767
00768
00769
00770
00771
00772
00773 void GDBController::parseProgramLocation(char *buf)
00774 {
00775 if (stateIsOn(s_silent))
00776 {
00777
00778
00779
00780 kdDebug(9012) << "App is paused <" << buf << ">" << endl;
00781 setStateOff(s_appBusy);
00782 return;
00783 }
00784
00785
00786 QRegExp regExp1("(.*):(\\d+):\\d+:[a-z]+:(0x[abcdef0-9]+)$");
00787 regExp1.setMinimal(true);
00788 if ( regExp1.search(buf, 0) >= 0 )
00789 {
00790 actOnProgramPause(QString());
00791 emit showStepInSource( regExp1.cap(1),
00792 regExp1.cap(2).toInt(),
00793 regExp1.cap(3) );
00794 return;
00795 }
00796
00797 if (stateIsOn(s_appBusy))
00798 actOnProgramPause(i18n("No source: %1").arg(QString(buf)));
00799 else
00800 emit dbgStatus (i18n("No source: %1").arg(QString(buf)), state_);
00801
00802
00803
00804 QRegExp regExp3("^(0x[abcdef0-9]+)");
00805 if (regExp3.search(buf, 0) >= 0)
00806 emit showStepInSource(QString(),
00807 -1,
00808 regExp3.cap(1));
00809 else
00810 emit showStepInSource("", -1, "");
00811
00812 }
00813
00814
00815
00816
00817 void GDBController::parseBacktraceList(char *buf)
00818 {
00819 frameStack_->parseGDBBacktraceList(buf);
00820 if (backtraceDueToProgramStop_)
00821 {
00822 varTree_->trimExcessFrames();
00823 VarFrameRoot *frame = varTree_->findFrame(currentFrame_, viewedThread_);
00824 if (frame)
00825 frame->setFrameName(
00826 frameStack_->getFrameName(currentFrame_, viewedThread_));
00827 backtraceDueToProgramStop_ = false;
00828 }
00829 }
00830
00831
00832
00833 void GDBController::parseThreadList(char *buf)
00834 {
00835 frameStack_->parseGDBThreadList(buf);
00836 viewedThread_ = frameStack_->viewedThread();
00837 varTree_->setCurrentThread(viewedThread_);
00838 }
00839
00840
00841
00842
00843
00844 void GDBController::parseBreakpointSet(char *buf)
00845 {
00846 if (GDBSetBreakpointCommand *BPCmd = dynamic_cast<GDBSetBreakpointCommand*>(currentCmd_))
00847 {
00848
00849
00850
00851 if (BPCmd->getKey() != -1)
00852 emit rawGDBBreakpointSet(buf, BPCmd->getKey());
00853 }
00854 }
00855
00856
00857
00858
00859 void GDBController::parseRequestedData(char *buf)
00860 {
00861 if (GDBItemCommand *gdbItemCommand = dynamic_cast<GDBItemCommand*> (currentCmd_))
00862 {
00863
00864 VarItem *item = gdbItemCommand->getItem();
00865 varTree_->viewport()->setUpdatesEnabled(false);
00866 item->updateValue(buf);
00867 item->trim();
00868 varTree_->viewport()->setUpdatesEnabled(true);
00869 varTree_->repaint();
00870 }
00871 }
00872
00873
00874
00875
00876 void GDBController::parseWhatis(char *buf)
00877 {
00878 if (GDBItemCommand *gdbItemCommand = dynamic_cast<GDBItemCommand*> (currentCmd_))
00879 {
00880
00881 VarItem *item = gdbItemCommand->getItem();
00882 varTree_->viewport()->setUpdatesEnabled(false);
00883
00884 item->updateType(buf);
00885
00886
00887 varTree_->viewport()->setUpdatesEnabled(true);
00888 varTree_->repaint();
00889 }
00890 }
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 void GDBController::parseFrameSelected(char *buf)
00910 {
00911 char lookup[3] = {BLOCK_START, SRC_POSITION, 0};
00912 if (char *start = strstr(buf, lookup))
00913 {
00914 if (char *end = strchr(start, '\n'))
00915 *end = 0;
00916 parseProgramLocation(start+2);
00917 return;
00918 }
00919
00920 if (!stateIsOn(s_silent))
00921 {
00922 emit showStepInSource("", -1, "");
00923 emit dbgStatus (i18n("No source: %1").arg(QString(buf)), state_);
00924 }
00925 }
00926
00927
00928
00929
00930
00931
00932
00933 void GDBController::parseLocals(char type, char *buf)
00934 {
00935 varTree_->viewport()->setUpdatesEnabled(false);
00936
00937
00938 VarFrameRoot *frame = varTree_->findFrame(currentFrame_, viewedThread_);
00939 if (!frame)
00940 {
00941 frame = new VarFrameRoot(varTree_, currentFrame_, viewedThread_);
00942 frame->setFrameName(
00943 frameStack_->getFrameName(currentFrame_, viewedThread_));
00944 }
00945
00946 Q_ASSERT(frame);
00947
00948 if (type == (char) ARGS)
00949 {
00950 frame->setParams(buf);
00951 }
00952 else
00953 {
00954 frame->setLocals(buf);
00955
00956
00957
00958
00959
00960
00961 if (currentFrame_ == 0 || viewedThread_ == -1)
00962 varTree_->trim();
00963 else
00964 frame->trim();
00965 }
00966
00967 varTree_->viewport()->setUpdatesEnabled(true);
00968 varTree_->repaint();
00969 }
00970
00971
00972
00973
00974
00975
00976 char *GDBController::parseCmdBlock(char *buf)
00977 {
00978 Q_ASSERT(*buf == (char)BLOCK_START);
00979
00980
00981 char *end = 0;
00982 switch (*(buf+1))
00983 {
00984 case IDLE:
00985
00986 return buf+1;
00987
00988 case SRC_POSITION:
00989
00990
00991
00992 if((end = strchr(buf, '\n')))
00993 *end = 0;
00994 break;
00995
00996 default:
00997 {
00998
00999 char lookup[3] = {BLOCK_START, *(buf+1), 0};
01000 if ((end = strstr(buf+2, lookup)))
01001 {
01002 *end = 0;
01003 end++;
01004 }
01005 break;
01006 }
01007 }
01008
01009 if (end)
01010 {
01011 char cmdType = *(buf+1);
01012 buf +=2;
01013 switch (cmdType)
01014 {
01015 case FRAME:
01016 parseFrameSelected (buf);
01017 break;
01018 case SET_BREAKPT:
01019 parseBreakpointSet (buf);
01020 break;
01021 case SRC_POSITION:
01022 parseProgramLocation (buf);
01023 break;
01024 case ARGS:
01025 case LOCALS:
01026 parseLocals (cmdType, buf);
01027 break;
01028 case DATAREQUEST:
01029 parseRequestedData (buf);
01030 break;
01031 case WHATIS:
01032 parseWhatis (buf);
01033 break;
01034 case BPLIST:
01035 emit rawGDBBreakpointList (buf);
01036 break;
01037 case BACKTRACE:
01038 parseBacktraceList (buf);
01039 break;
01040 case INFOTHREAD:
01041 parseThreadList (buf);
01042 break;
01043 case DISASSEMBLE:
01044 emit rawGDBDisassemble (buf);
01045 break;
01046 case MEMDUMP:
01047 emit rawGDBMemoryDump (buf);
01048 break;
01049 case REGISTERS:
01050 emit rawGDBRegisters (buf);
01051 break;
01052 case LIBRARIES:
01053 emit rawGDBLibraries (buf);
01054 break;
01055
01056
01057
01058
01059
01060
01061 default:
01062 break;
01063 }
01064
01065
01066
01067 if (currentCmd_ && currentCmd_->typeMatch(cmdType))
01068 {
01069 delete currentCmd_;
01070 currentCmd_ = 0;
01071 }
01072 }
01073
01074 return end;
01075 }
01076
01077
01078
01079
01080
01081 char *GDBController::parseOther(char *buf)
01082 {
01083
01084 Q_ASSERT (*buf != (char)BLOCK_START);
01085
01086
01087 char *end = buf;
01088 while (*end)
01089 {
01090 if (*end=='(')
01091 {
01092
01093
01094
01095
01096
01097
01098 if (strncmp(end, "(no debugging symbols found)...", 31) == 0)
01099 {
01100
01101 return end+30;
01102 }
01103 }
01104
01105 if (*end=='\n')
01106 {
01107
01108 if ((end-buf > 2) && (*(end-1) == ' ' && *(end-2) == ',') || (*(end-1) == ':'))
01109 *end = ' ';
01110 else
01111 {
01112 *end = 0;
01113 parseLine(buf);
01114 return end;
01115 }
01116 }
01117
01118
01119
01120 if (*end == (char)BLOCK_START)
01121 return end-1;
01122
01123 end++;
01124 }
01125
01126 return 0;
01127 }
01128
01129
01130
01131 char *GDBController::parse(char *buf)
01132 {
01133 char *unparsed = buf;
01134 while (*unparsed)
01135 {
01136 char *parsed;
01137 if (*unparsed == (char)BLOCK_START)
01138 parsed = parseCmdBlock(unparsed);
01139 else
01140 parsed = parseOther(unparsed);
01141
01142 if (!parsed)
01143 break;
01144
01145
01146 unparsed = parsed+1;
01147 }
01148
01149 return (unparsed==buf) ? 0 : unparsed;
01150 }
01151
01152
01153
01154 void GDBController::setBreakpoint(const QCString &BPSetCmd, int key)
01155 {
01156 queueCmd(new GDBSetBreakpointCommand(BPSetCmd, key));
01157 }
01158
01159
01160
01161 void GDBController::clearBreakpoint(const QCString &BPClearCmd)
01162 {
01163 queueCmd(new GDBCommand(BPClearCmd, NOTRUNCMD, NOTINFOCMD));
01164
01165
01166
01167 queueCmd(new GDBCommand("info breakpoints", NOTRUNCMD, NOTINFOCMD, BPLIST));
01168 }
01169
01170
01171
01172 void GDBController::modifyBreakpoint( const Breakpoint& BP )
01173 {
01174 Q_ASSERT(BP.isActionModify());
01175 if (BP.dbgId()>0)
01176 {
01177 if (BP.changedCondition())
01178 queueCmd(new GDBCommand(QCString().sprintf("condition %d %s",
01179 BP.dbgId(), BP.conditional().latin1()),
01180 NOTRUNCMD, NOTINFOCMD));
01181
01182 if (BP.changedIgnoreCount())
01183 queueCmd(new GDBCommand(QCString().sprintf("ignore %d %d",
01184 BP.dbgId(), BP.ignoreCount()),
01185 NOTRUNCMD, NOTINFOCMD));
01186
01187 if (BP.changedEnable())
01188 queueCmd(new GDBCommand(QCString().sprintf("%s %d",
01189 BP.isEnabled() ? "enable" : "disable",
01190 BP.dbgId()), NOTRUNCMD, NOTINFOCMD));
01191
01192
01193
01194
01195
01196 queueCmd(new GDBCommand("info breakpoints", NOTRUNCMD, NOTINFOCMD,
01197 BPLIST));
01198 }
01199 }
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209 void GDBController::slotStart(const QString& shell, const DomUtil::PairList& run_envvars, const QString& run_directory, const QString &application, const QString& run_arguments)
01210 {
01211 badCore_ = QString();
01212
01213 Q_ASSERT (!dbgProcess_ && !tty_);
01214
01215 tty_ = new STTY(config_dbgTerminal_, "konsole");
01216 if (!config_dbgTerminal_)
01217 {
01218 connect( tty_, SIGNAL(OutOutput(const char*)), SIGNAL(ttyStdout(const char*)) );
01219 connect( tty_, SIGNAL(ErrOutput(const char*)), SIGNAL(ttyStderr(const char*)) );
01220 }
01221
01222 QString tty(tty_->getSlave());
01223 if (tty.isEmpty())
01224 {
01225 KMessageBox::error(0, i18n("GDB cannot use the tty* or pty* devices.\n"
01226 "Check the settings on /dev/tty* and /dev/pty*\n"
01227 "As root you may need to \"chmod ug+rw\" tty* and pty* devices "
01228 "and/or add the user to the tty group using "
01229 "\"usermod -G tty username\"."));
01230
01231 delete tty_;
01232 tty_ = 0;
01233 return;
01234 }
01235
01236 dbgProcess_ = new KProcess;
01237
01238 connect( dbgProcess_, SIGNAL(receivedStdout(KProcess *, char *, int)),
01239 this, SLOT(slotDbgStdout(KProcess *, char *, int)) );
01240
01241 connect( dbgProcess_, SIGNAL(receivedStderr(KProcess *, char *, int)),
01242 this, SLOT(slotDbgStderr(KProcess *, char *, int)) );
01243
01244 connect( dbgProcess_, SIGNAL(wroteStdin(KProcess *)),
01245 this, SLOT(slotDbgWroteStdin(KProcess *)) );
01246
01247 connect( dbgProcess_, SIGNAL(processExited(KProcess*)),
01248 this, SLOT(slotDbgProcessExited(KProcess*)) );
01249
01250 application_ = application;
01251 if (!shell.isEmpty())
01252 {
01253 *dbgProcess_ << "/bin/sh" << "-c" << shell + " " +config_gdbPath_
01254 + "gdb " + application + " -fullname -nx -quiet";
01255 emit gdbStdout(QString( "/bin/sh -c " + shell + " " +config_gdbPath_
01256 + "gdb " + application + " -fullname -nx -quiet" ).latin1());
01257 }
01258 else
01259 {
01260 *dbgProcess_ << config_gdbPath_ + "gdb" << application
01261 << "-fullname" << "-nx" << "-quiet";
01262 emit gdbStdout(QString( config_gdbPath_ + "gdb " + application +
01263 " -fullname -nx -quiet" ).latin1());
01264 }
01265
01266 dbgProcess_->start( KProcess::NotifyOnExit,
01267 KProcess::Communication(KProcess::All));
01268
01269 setStateOff(s_dbgNotStarted);
01270 emit dbgStatus ("", state_);
01271
01272
01273
01274
01275
01276 queueCmd(new GDBCommand("set edit off", NOTRUNCMD, NOTINFOCMD, 0));
01277 queueCmd(new GDBCommand("set confirm off", NOTRUNCMD, NOTINFOCMD));
01278
01279 if (config_displayStaticMembers_)
01280 queueCmd(new GDBCommand("set print static-members on", NOTRUNCMD,
01281 NOTINFOCMD));
01282 else
01283 queueCmd(new GDBCommand("set print static-members off", NOTRUNCMD, NOTINFOCMD));
01284
01285 queueCmd(new GDBCommand(QCString("tty ")+tty.latin1(), NOTRUNCMD, NOTINFOCMD));
01286
01287
01288 queueCmd(new GDBCommand("set width 0", NOTRUNCMD, NOTINFOCMD));
01289 queueCmd(new GDBCommand("set height 0", NOTRUNCMD, NOTINFOCMD));
01290
01291
01292
01293
01294
01295
01296 if (config_breakOnLoadingLibrary_)
01297 queueCmd(new GDBCommand("set stop-on 1", NOTRUNCMD, NOTINFOCMD));
01298 else
01299 queueCmd(new GDBCommand("set stop-on 0", NOTRUNCMD, NOTINFOCMD));
01300
01301 queueCmd(new GDBCommand("handle SIG32 pass nostop noprint", NOTRUNCMD,
01302 NOTINFOCMD));
01303 queueCmd(new GDBCommand("handle SIG43 pass nostop noprint", NOTRUNCMD,
01304 NOTINFOCMD));
01305
01306
01307
01308 if (config_asmDemangle_)
01309 queueCmd(new GDBCommand("set print asm-demangle on", NOTRUNCMD, NOTINFOCMD));
01310 else
01311 queueCmd(new GDBCommand("set print asm-demangle off", NOTRUNCMD, NOTINFOCMD));
01312
01313
01314 queueCmd(new GDBCommand(QCString().sprintf("set output-radix %d", config_outputRadix_), NOTRUNCMD, NOTINFOCMD));
01315
01316
01317 QCString tmp( "cd " + QFile::encodeName( run_directory ));
01318 queueCmd(new GDBCommand(tmp, NOTRUNCMD, NOTINFOCMD));
01319
01320
01321 if (!run_arguments.isEmpty())
01322 queueCmd(new GDBCommand(QCString("set args ") + run_arguments.latin1(), NOTRUNCMD, NOTINFOCMD));
01323
01324
01325
01326
01327
01328
01329 QString environstr;
01330 DomUtil::PairList::ConstIterator it;
01331 for (it = run_envvars.begin(); it != run_envvars.end(); ++it)
01332 {
01333 environstr = "set environment ";
01334 environstr += (*it).first;
01335 environstr += "=";
01336 environstr += (*it).second;
01337 queueCmd(new GDBCommand(environstr.latin1(), NOTRUNCMD, NOTINFOCMD));
01338 }
01339
01340
01341 emit acceptPendingBPs();
01342
01343
01344
01345
01346
01347 }
01348
01349
01350
01351 void GDBController::slotStopDebugger()
01352 {
01353 kdDebug(9012) << "GDBController::slotStopDebugger() called" << endl;
01354 if (stateIsOn(s_shuttingDown) || !dbgProcess_)
01355 return;
01356
01357 setStateOn(s_shuttingDown|s_silent);
01358 kdDebug(9012) << "GDBController::slotStopDebugger() executing" << endl;
01359 destroyCmds();
01360
01361 QTime start;
01362 QTime now;
01363
01364
01365
01366 if (stateIsOn(s_appBusy))
01367 {
01368 kdDebug(9012) << "gdb busy on shutdown - stopping gdb (SIGINT)" << endl;
01369 dbgProcess_->kill(SIGINT);
01370 start = QTime::currentTime();
01371 while (-1)
01372 {
01373 kapp->processEvents(20);
01374 now = QTime::currentTime();
01375 if (!stateIsOn(s_appBusy) || start.msecsTo( now ) > 2000)
01376 break;
01377 }
01378 }
01379
01380
01381
01382 if (stateIsOn(s_attached))
01383 {
01384 kdDebug(9012) << "App is busy" << endl;
01385 setStateOn(s_appBusy);
01386 const char *detach="detach\n";
01387 if (!dbgProcess_->writeStdin(detach, strlen(detach)))
01388 kdDebug(9012) << "failed to write 'detach' to gdb" << endl;
01389 emit gdbStdout("(gdb) detach");
01390 start = QTime::currentTime();
01391 while (-1)
01392 {
01393 kapp->processEvents(20);
01394 now = QTime::currentTime();
01395 if (!stateIsOn(s_attached) || start.msecsTo( now ) > 2000)
01396 break;
01397 }
01398 }
01399
01400
01401 kdDebug(9012) << "App is busy" << endl;
01402 setStateOn(s_appBusy);
01403 const char *quit="quit\n";
01404 if (!dbgProcess_->writeStdin(quit, strlen(quit)))
01405 kdDebug(9012) << "failed to write 'quit' to gdb" << endl;
01406
01407 emit gdbStdout("(gdb) quit");
01408 start = QTime::currentTime();
01409 while (-1)
01410 {
01411 kapp->processEvents(20);
01412 now = QTime::currentTime();
01413 if (stateIsOn(s_programExited) || start.msecsTo( now ) > 2000)
01414 break;
01415 }
01416
01417
01418 if (!stateIsOn(s_programExited))
01419 {
01420 kdDebug(9012) << "gdb not shutdown - killing" << endl;
01421 dbgProcess_->kill(SIGKILL);
01422 }
01423
01424 delete dbgProcess_; dbgProcess_ = 0;
01425 delete tty_; tty_ = 0;
01426
01427 state_ = s_dbgNotStarted | s_appNotStarted | s_silent;
01428 emit dbgStatus (i18n("Debugger stopped"), state_);
01429 }
01430
01431
01432
01433 void GDBController::slotCoreFile(const QString &coreFile)
01434 {
01435 setStateOff(s_silent);
01436 setStateOn(s_core);
01437
01438 queueCmd(new GDBCommand(QCString("core ") + coreFile.latin1(), NOTRUNCMD,
01439 NOTINFOCMD, 0));
01440
01441
01442
01443
01444
01445 queueCmd(new GDBCommand("backtrace", NOTRUNCMD, INFOCMD, BACKTRACE));
01446
01447 if (stateIsOn(s_viewLocals))
01448 {
01449 queueCmd(new GDBCommand("info args", NOTRUNCMD, INFOCMD, ARGS));
01450 queueCmd(new GDBCommand("info local", NOTRUNCMD, INFOCMD, LOCALS));
01451 }
01452 }
01453
01454
01455
01456 void GDBController::slotAttachTo(int pid)
01457 {
01458 setStateOff(s_appNotStarted|s_programExited|s_silent);
01459 setStateOn(s_attached);
01460 queueCmd(new GDBCommand(
01461 QCString().sprintf("attach %d", pid), NOTRUNCMD, NOTINFOCMD, 0));
01462
01463
01464
01465
01466
01467 queueCmd(new GDBCommand("backtrace", NOTRUNCMD, INFOCMD, BACKTRACE));
01468
01469 if (stateIsOn(s_viewLocals))
01470 {
01471 queueCmd(new GDBCommand("info args", NOTRUNCMD, INFOCMD, ARGS));
01472 queueCmd(new GDBCommand("info local", NOTRUNCMD, INFOCMD, LOCALS));
01473 }
01474 }
01475
01476
01477
01478 void GDBController::slotRun()
01479 {
01480 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01481 return;
01482
01483 if (stateIsOn(s_appNotStarted)) {
01484
01485 if (!config_runShellScript_.isEmpty()) {
01486
01487 QCString tty(tty_->getSlave().latin1());
01488 QCString options = QCString(" 2>&1 >") + tty + QCString(" <") + tty;
01489
01490 KProcess *proc = new KProcess;
01491
01492 *proc << "sh" << "-c";
01493 *proc << config_runShellScript_ +
01494 " " + application_.latin1() + options;
01495 proc->start(KProcess::DontCare);
01496 }
01497
01498 if (!config_runGdbScript_.isEmpty()) {
01499
01500
01501
01502
01503
01504
01505
01506 queueCmd(new GDBCommand("source " + config_runGdbScript_,
01507 RUNCMD, NOTINFOCMD, 0));
01508
01509
01510 }
01511 else {
01512 queueCmd(new GDBCommand("run", RUNCMD, NOTINFOCMD, 0));
01513 }
01514 }
01515 else {
01516 queueCmd(new GDBCommand("continue", RUNCMD, NOTINFOCMD, 0));
01517 }
01518 }
01519
01520
01521
01522 void GDBController::slotRunUntil(const QString &fileName, int lineNum)
01523 {
01524 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01525 return;
01526
01527 if (fileName.isEmpty())
01528 queueCmd(new GDBCommand( QCString().sprintf("until %d", lineNum),
01529 RUNCMD, NOTINFOCMD, 0));
01530 else
01531 queueCmd(new GDBCommand(
01532 QCString().sprintf("until %s:%d", fileName.latin1(), lineNum),
01533 RUNCMD, NOTINFOCMD, 0));
01534 }
01535
01536
01537
01538 void GDBController::slotStepInto()
01539 {
01540 if (stateIsOn(s_appBusy|s_appNotStarted|s_shuttingDown))
01541 return;
01542
01543 queueCmd(new GDBCommand("step", RUNCMD, NOTINFOCMD, 0));
01544 }
01545
01546
01547
01548 void GDBController::slotStepIntoIns()
01549 {
01550 if (stateIsOn(s_appBusy|s_appNotStarted|s_shuttingDown))
01551 return;
01552
01553 queueCmd(new GDBCommand("stepi", RUNCMD, NOTINFOCMD, 0));
01554 }
01555
01556
01557
01558 void GDBController::slotStepOver()
01559 {
01560 if (stateIsOn(s_appBusy|s_appNotStarted|s_shuttingDown))
01561 return;
01562
01563 queueCmd(new GDBCommand("next", RUNCMD, NOTINFOCMD, 0));
01564 }
01565
01566
01567
01568 void GDBController::slotStepOverIns()
01569 {
01570 if (stateIsOn(s_appBusy|s_appNotStarted|s_shuttingDown))
01571 return;
01572
01573 queueCmd(new GDBCommand("nexti", RUNCMD, NOTINFOCMD, 0));
01574 }
01575
01576
01577
01578 void GDBController::slotStepOutOff()
01579 {
01580 if (stateIsOn(s_appBusy|s_appNotStarted|s_shuttingDown))
01581 return;
01582
01583 queueCmd(new GDBCommand("finish", RUNCMD, NOTINFOCMD, 0));
01584 }
01585
01586
01587
01588
01589 void GDBController::slotBreakInto()
01590 {
01591 pauseApp();
01592 }
01593
01594
01595
01596
01597 void GDBController::slotBPState( const Breakpoint& BP )
01598 {
01599
01600 if (stateIsOn(s_dbgNotStarted|s_shuttingDown) || !BP.isPending() ||
01601 BP.isActionDie())
01602 return;
01603
01604
01605
01606
01607 bool restart = false;
01608 if (stateIsOn(s_appBusy))
01609 {
01610 if (!config_forceBPSet_)
01611 return;
01612
01613
01614
01615 setStateOn(s_silent);
01616 pauseApp();
01617 restart = true;
01618 }
01619
01620 if (BP.isActionAdd())
01621 {
01622 setBreakpoint(BP.dbgSetCommand().latin1(), BP.key());
01623
01624 }
01625 else
01626 {
01627 if (BP.isActionClear())
01628 {
01629 clearBreakpoint(BP.dbgRemoveCommand().latin1());
01630
01631 }
01632 else
01633 {
01634 if (BP.isActionModify())
01635 {
01636 modifyBreakpoint(BP);
01637 }
01638 }
01639 }
01640
01641 if (restart)
01642 queueCmd(new GDBCommand("continue", RUNCMD, NOTINFOCMD, 0));
01643 }
01644
01645
01646
01647 void GDBController::slotClearAllBreakpoints()
01648 {
01649
01650 if (stateIsOn(s_dbgNotStarted|s_shuttingDown))
01651 return;
01652
01653 bool restart = false;
01654 if (stateIsOn(s_appBusy))
01655 {
01656 if (!config_forceBPSet_)
01657 return;
01658
01659
01660
01661 setStateOn(s_silent);
01662 pauseApp();
01663 restart = true;
01664 }
01665
01666 queueCmd(new GDBCommand("delete", NOTRUNCMD, NOTINFOCMD));
01667
01668
01669
01670 queueCmd(new GDBCommand("info breakpoints", NOTRUNCMD, NOTINFOCMD, BPLIST));
01671
01672 if (restart)
01673 queueCmd(new GDBCommand("continue", RUNCMD, NOTINFOCMD, 0));
01674 }
01675
01676
01677
01678 void GDBController::slotDisassemble(const QString &start, const QString &end)
01679 {
01680 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01681 return;
01682
01683 QCString cmd = QCString().sprintf("disassemble %s %s", start.latin1(), end.latin1());
01684 queueCmd(new GDBCommand(cmd, NOTRUNCMD, INFOCMD, DISASSEMBLE));
01685 }
01686
01687
01688
01689 void GDBController::slotMemoryDump(const QString &address, const QString &amount)
01690 {
01691 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01692 return;
01693
01694 QCString cmd = QCString().sprintf("x/%sb %s", amount.latin1(),
01695 address.latin1());
01696 queueCmd(new GDBCommand(cmd, NOTRUNCMD, INFOCMD, MEMDUMP));
01697 }
01698
01699
01700
01701 void GDBController::slotRegisters()
01702 {
01703 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01704 return;
01705
01706 queueCmd(new GDBCommand("info all-registers", NOTRUNCMD, INFOCMD, REGISTERS));
01707 }
01708
01709
01710
01711 void GDBController::slotLibraries()
01712 {
01713 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01714 return;
01715
01716 queueCmd(new GDBCommand("info sharedlibrary", NOTRUNCMD, INFOCMD, LIBRARIES));
01717 }
01718
01719
01720
01721 void GDBController::slotSelectFrame(int frameNo, int threadNo, bool needFrames)
01722 {
01723 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01724 return;
01725
01726
01727
01728
01729
01730
01731
01732 if (threadNo != -1)
01733 {
01734
01735
01736
01737 if (viewedThread_ != -1)
01738 {
01739 if (viewedThread_ != threadNo)
01740 queueCmd(new GDBCommand(QCString().sprintf("thread %d",
01741 threadNo), NOTRUNCMD, INFOCMD, SWITCHTHREAD));
01742 }
01743 }
01744
01745 queueCmd(new GDBCommand(QCString().sprintf("frame %d",
01746 frameNo), NOTRUNCMD, INFOCMD, FRAME));
01747
01748 if (needFrames)
01749 queueCmd(new GDBCommand("backtrace", NOTRUNCMD, INFOCMD,
01750 BACKTRACE));
01751
01752
01753
01754 viewedThread_ = threadNo;
01755 currentFrame_ = frameNo;
01756
01757
01758
01759 VarFrameRoot *frame = varTree_->findFrame(frameNo, viewedThread_);
01760 if (!frame)
01761 {
01762 frame = new VarFrameRoot(varTree_, currentFrame_, viewedThread_);
01763 frame->setFrameName(
01764 frameStack_->getFrameName(currentFrame_, viewedThread_));
01765 }
01766
01767 Q_ASSERT(frame);
01768 if (stateIsOn(s_viewLocals))
01769 {
01770
01771 if (frame->needLocals())
01772 {
01773
01774
01775 queueCmd(new GDBCommand("info args", NOTRUNCMD, INFOCMD, ARGS));
01776 queueCmd(new GDBCommand("info local", NOTRUNCMD, INFOCMD, LOCALS));
01777 }
01778 }
01779 }
01780
01781
01782
01783 void GDBController::slotVarItemConstructed(VarItem *item)
01784 {
01785 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01786 return;
01787
01788
01789
01790
01791 QString strName = item->fullName();
01792 strName.remove( QRegExp("/[xd] ", FALSE) );
01793 queueCmd(new GDBItemCommand(item, QCString("whatis ") + strName.latin1(),
01794 false, WHATIS));
01795 }
01796
01797
01798
01799
01800
01801 void GDBController::slotExpandItem(TrimmableItem *genericItem)
01802 {
01803 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01804 return;
01805
01806 VarItem *varItem;
01807 if ((varItem = dynamic_cast<VarItem*>(genericItem)))
01808 {
01809 switch (varItem->getDataType())
01810 {
01811 case typePointer:
01812 queueCmd(new GDBPointerCommand(varItem));
01813 break;
01814
01815 default:
01816
01817
01818 QString strCmd = varItem->fullName();
01819 int iFound = strCmd.find( QRegExp("./[xd] ", FALSE) );
01820 if (iFound != -1) {
01821 strCmd.prepend( strCmd.mid(iFound+1, 3) );
01822 strCmd.replace( QRegExp("./[xd] "), "." );
01823 }
01824 queueCmd(new GDBItemCommand(varItem, QCString("print ") + strCmd.latin1())); break;
01825 }
01826 return;
01827 }
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857 }
01858
01859
01860
01861
01862
01863
01864 void GDBController::slotExpandUserItem(VarItem *item, const QCString &userRequest)
01865 {
01866 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01867 return;
01868
01869 Q_ASSERT(item);
01870
01871
01872 if (userRequest.isEmpty())
01873 return;
01874
01875 queueCmd(new GDBItemCommand(item, QCString("print ")+userRequest.data(),
01876 false, DATAREQUEST));
01877 }
01878
01879
01880
01881
01882
01883 void GDBController::slotSetLocalViewState(bool onOff)
01884 {
01885 if (onOff)
01886 setStateOn(s_viewLocals);
01887 else
01888 setStateOff(s_viewLocals);
01889
01890 kdDebug(9012) << (onOff ? "<Locals ON>": "<Locals OFF>") << endl;
01891 }
01892
01893
01894
01895
01896 void GDBController::slotDbgStdout(KProcess *, char *buf, int buflen)
01897 {
01898 static bool parsing = false;
01899
01900 QCString msg(buf, buflen+1);
01901
01902 msg.replace( QRegExp("\032."), "" );
01903 emit gdbStdout(msg);
01904
01905
01906
01907 holdingZone_ += QCString(buf, buflen+1);
01908
01909
01910 if (parsing)
01911 {
01912 kdDebug(9012) << "Already parsing" << endl;
01913 return;
01914 }
01915
01916 while (true)
01917 {
01918
01919 if (gdbOutputLen_+(int)holdingZone_.length()+1 > gdbSizeofBuf_)
01920 {
01921 gdbSizeofBuf_ = gdbOutputLen_+2*(holdingZone_.length()+1);
01922 char *newBuf = new char[gdbSizeofBuf_];
01923 if (gdbOutputLen_)
01924 memcpy(newBuf, gdbOutput_, gdbOutputLen_+1);
01925 delete[] gdbOutput_;
01926 gdbOutput_ = newBuf;
01927 }
01928
01929
01930
01931
01932
01933
01934 qstrcpy(gdbOutput_+gdbOutputLen_, holdingZone_);
01935 gdbOutputLen_ += holdingZone_.length();
01936 *(gdbOutput_+gdbOutputLen_) = 0;
01937 holdingZone_ = "";
01938
01939
01940
01941
01942 parsing = true;
01943 char *nowAt = parse(gdbOutput_);
01944 parsing = false;
01945
01946 if (nowAt)
01947 {
01948
01949 Q_ASSERT(nowAt <= gdbOutput_+gdbOutputLen_+1);
01950 gdbOutputLen_ = strlen(nowAt);
01951
01952
01953 if (gdbOutputLen_)
01954 memmove(gdbOutput_, nowAt, gdbOutputLen_);
01955 else
01956 *gdbOutput_ = 0;
01957 }
01958
01959
01960
01961
01962 if (!nowAt && !holdingZone_.length())
01963 break;
01964 }
01965
01966
01967 executeCmd();
01968 }
01969
01970
01971
01972 void GDBController::slotDbgStderr(KProcess *proc, char *buf, int buflen)
01973 {
01974
01975 kdDebug(9012) << "STDERR: " << QString::fromLatin1(buf, buflen+1) << endl;
01976 slotDbgStdout(proc, buf, buflen);
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006 }
02007
02008
02009
02010 void GDBController::slotDbgWroteStdin(KProcess *)
02011 {
02012 setStateOff(s_waitForWrite);
02013
02014
02015 executeCmd();
02016 }
02017
02018
02019
02020 void GDBController::slotDbgProcessExited(KProcess*)
02021 {
02022 destroyCmds();
02023 state_ = s_appNotStarted|s_programExited|(state_&(s_viewLocals|s_shuttingDown));
02024 emit dbgStatus (i18n("Process exited"), state_);
02025
02026 emit gdbStdout("(gdb) Process exited\n");
02027 }
02028
02029
02030
02031 void GDBController::slotUserGDBCmd(const QString& cmd)
02032 {
02033 kdDebug(9012) << "Requested user cmd: " << cmd << endl;
02034 if (cmd.startsWith("step") || cmd.startsWith("c"))
02035 {
02036 queueCmd(new GDBCommand(cmd.latin1(), RUNCMD, NOTINFOCMD, 0));
02037 return;
02038 }
02039
02040 if (cmd.startsWith("info lo"))
02041 {
02042 queueCmd(new GDBCommand("info local", NOTRUNCMD, INFOCMD, LOCALS));
02043 return;
02044 }
02045
02046 if (cmd.startsWith("info ar"))
02047 {
02048 queueCmd(new GDBCommand("info args", NOTRUNCMD, INFOCMD, ARGS));
02049 return;
02050 }
02051
02052 if (cmd.startsWith("info th"))
02053 {
02054 queueCmd(new GDBCommand("info thread", NOTRUNCMD, INFOCMD, INFOTHREAD), true);
02055 return;
02056 }
02057
02058 if (cmd.startsWith("ba") || cmd.startsWith("bt"))
02059 {
02060 queueCmd(new GDBCommand("backtrace", NOTRUNCMD, INFOCMD, BACKTRACE), true);
02061 return;
02062 }
02063
02064 QRegExp frame("^fr[ame]*\\s+(\\d+)");
02065 if ( frame.search(cmd) >= 0 )
02066 {
02067 slotSelectFrame(frame.cap(1).toInt(), viewedThread_, true);
02068 return;
02069 }
02070
02071 QRegExp thread("^th[read]*\\s+(\\d+)");
02072 if ( thread.search(cmd) >= 0 )
02073 {
02074 int threadNo = thread.cap(1).toInt();
02075 int frameNo = currentFrame_;
02076 if (threadNo != viewedThread_)
02077 frameNo = 0;
02078
02079 slotSelectFrame(frameNo, threadNo, true);
02080 return;
02081 }
02082
02083 if (cmd.startsWith("qu"))
02084 {
02085 slotStopDebugger();
02086 return;
02087 }
02088
02089 kdDebug(9012) << "Parsing directly to gdb: " << cmd << endl;
02090 queueCmd(new GDBCommand(cmd.latin1(), NOTRUNCMD, INFOCMD, USERCMD));
02091 }
02092
02093 }
02094
02095
02096
02097
02098 #include "gdbcontroller.moc"