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