00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#include <qdir.h>
00015
#include <qvbox.h>
00016
#include <qwhatsthis.h>
00017
#include <qpopupmenu.h>
00018
00019
#include <kaction.h>
00020
#include <kdebug.h>
00021
#include <kfiledialog.h>
00022
#include <kdevgenericfactory.h>
00023
#include <kiconloader.h>
00024
#include <klocale.h>
00025
#include <kmainwindow.h>
00026
#include <kstatusbar.h>
00027
#include <kparts/part.h>
00028
#include <ktexteditor/viewcursorinterface.h>
00029
#include <kmessagebox.h>
00030
#include <kapplication.h>
00031
#include <dcopclient.h>
00032
#include <qtimer.h>
00033
00034
#include "kdevcore.h"
00035
#include "kdevproject.h"
00036
#include "kdevmainwindow.h"
00037
#include "kdevappfrontend.h"
00038
#include "kdevpartcontroller.h"
00039
#include "kdevdebugger.h"
00040
#include "domutil.h"
00041
#include "variablewidget.h"
00042
#include "gdbbreakpointwidget.h"
00043
#include "framestackwidget.h"
00044
#include "disassemblewidget.h"
00045
#include "processwidget.h"
00046
#include "gdbcontroller.h"
00047
#include "breakpoint.h"
00048
#include "dbgpsdlg.h"
00049
#include "dbgtoolbar.h"
00050
#include "memviewdlg.h"
00051
#include "gdbparser.h"
00052
#include "gdboutputwidget.h"
00053
#include "debuggerconfigwidget.h"
00054
#include "processlinemaker.h"
00055
00056
#include <iostream>
00057
00058
#include "debuggerpart.h"
00059
00060
namespace GDBDebugger
00061 {
00062
00063
static const KAboutData data(
"kdevdebugger",
I18N_NOOP(
"Debugger"),
"1.0");
00064
00065 typedef KDevGenericFactory<DebuggerPart> DebuggerFactory;
00066 K_EXPORT_COMPONENT_FACTORY( libkdevdebugger,
DebuggerFactory( &data ) )
00067
00068
DebuggerPart::
DebuggerPart(
QObject *parent, const
char *name, const
QStringList & ) :
00069
KDevPlugin( "CppDebugger", "debugger", parent, name ? name : "
DebuggerPart" ),
00070 controller(0)
00071 {
00072 setObjId(
"DebuggerInterface");
00073 setInstance(DebuggerFactory::instance());
00074
00075 setXMLFile(
"kdevdebugger.rc");
00076
00077 statusBarIndicator =
new QLabel(
" ", mainWindow()->statusBar());
00078 statusBarIndicator->setFixedWidth(15);
00079 mainWindow()->statusBar()->addWidget(statusBarIndicator, 0,
true);
00080 statusBarIndicator->show();
00081
00082
00083 variableWidget =
new VariableWidget();
00084 variableWidget->setEnabled(
false);
00085 variableWidget->setIcon(SmallIcon(
"math_brace"));
00086 variableWidget->setCaption(i18n(
"Variable Tree"));
00087 QWhatsThis::add
00088 (variableWidget, i18n(
"<b>Variable tree</b><p>"
00089
"The variable tree allows you to see "
00090
"the variable values as you step "
00091
"through your program using the internal "
00092
"debugger. Click the RMB on items in "
00093
"this view to get a popup menu.\n"
00094
"To speed up stepping through your code "
00095
"leave the tree items closed and add the "
00096
"variable(s) to the watch section.\n"
00097
"To change a variable value in your "
00098
"running app use a watch variable (eg a=5)."));
00099 mainWindow()->embedSelectView(variableWidget, i18n(
"Variables / Watch"), i18n(
"Debugger variable-view"));
00100 mainWindow()->setViewAvailable(variableWidget,
false);
00101
00102 gdbBreakpointWidget =
new GDBBreakpointWidget();
00103 gdbBreakpointWidget->setCaption(i18n(
"Breakpoint List"));
00104 QWhatsThis::add
00105 (gdbBreakpointWidget, i18n(
"<b>Breakpoint list</b><p>"
00106
"Displays a list of breakpoints with "
00107
"their current status. Clicking on a "
00108
"breakpoint item allows you to change "
00109
"the breakpoint and will take you "
00110
"to the source in the editor window."));
00111 gdbBreakpointWidget->setIcon( SmallIcon(
"stop") );
00112 mainWindow()->embedOutputView(gdbBreakpointWidget, i18n(
"Breakpoints"), i18n(
"Debugger breakpoints"));
00113
00114 framestackWidget =
new FramestackWidget();
00115 framestackWidget->setEnabled(
false);
00116 framestackWidget->setCaption(i18n(
"Frame Stack"));
00117 QWhatsThis::add
00118 (framestackWidget, i18n(
"<b>Frame stack</b><p>"
00119
"Often referred to as the \"call stack\", "
00120
"this is a list showing what function is "
00121
"currently active and who called each "
00122
"function to get to this point in your "
00123
"program. By clicking on an item you "
00124
"can see the values in any of the "
00125
"previous calling functions."));
00126 framestackWidget->setIcon( SmallIcon(
"table") );
00127 mainWindow()->embedOutputView(framestackWidget, i18n(
"Frame Stack"), i18n(
"Debugger function call stack"));
00128 mainWindow()->setViewAvailable(framestackWidget,
false);
00129
00130 disassembleWidget =
new DisassembleWidget();
00131 disassembleWidget->setEnabled(
false);
00132 disassembleWidget->setCaption(i18n(
"Machine Code Display"));
00133 QWhatsThis::add
00134 (disassembleWidget, i18n(
"<b>Machine code display</b><p>"
00135
"A machine code view into your running "
00136
"executable with the current instruction "
00137
"highlighted. You can step instruction by "
00138
"instruction using the debuggers toolbar "
00139
"buttons of \"step over\" instruction and "
00140
"\"step into\" instruction."));
00141 disassembleWidget->setIcon( SmallIcon(
"gear") );
00142 mainWindow()->embedOutputView(disassembleWidget, i18n(
"Disassemble"),
00143 i18n(
"Debugger disassemble view"));
00144 mainWindow()->setViewAvailable(disassembleWidget,
false);
00145
00146 gdbOutputWidget =
new GDBOutputWidget;
00147 gdbOutputWidget->setEnabled(
false);
00148 gdbOutputWidget->setIcon( SmallIcon(
"inline_image") );
00149 QWhatsThis::add
00150 (gdbOutputWidget, i18n(
"<b>GDB output</b><p>"
00151
"Shows all gdb commands being executed. "
00152
"You can also issue any other gdb command while debugging."));
00153 mainWindow()->embedOutputView(gdbOutputWidget, i18n(
"GDB"),
00154 i18n(
"GDB output"));
00155 mainWindow()->setViewAvailable(gdbOutputWidget,
false);
00156
00157
VariableTree *variableTree = variableWidget->varTree();
00158
00159
00160 connect( variableTree, SIGNAL(selectFrame(
int,
int)),
00161 framestackWidget, SLOT(slotSelectFrame(
int,
int)));
00162
00163
00164 connect( gdbBreakpointWidget, SIGNAL(refreshBPState(
const Breakpoint&)),
00165
this, SLOT(slotRefreshBPState(
const Breakpoint&)));
00166 connect( gdbBreakpointWidget, SIGNAL(publishBPState(
const Breakpoint&)),
00167
this, SLOT(slotRefreshBPState(
const Breakpoint&)));
00168 connect( gdbBreakpointWidget, SIGNAL(gotoSourcePosition(
const QString&,
int)),
00169
this, SLOT(slotGotoSource(
const QString&,
int)) );
00170
00171
00172
KAction *action;
00173
00174 action =
new KAction(i18n(
"&Start"),
"1rightarrow", CTRL+SHIFT+Key_F9,
00175
this, SLOT(slotRun()),
00176 actionCollection(),
"debug_run");
00177 action->setToolTip( i18n(
"Start in debugger") );
00178 action->setWhatsThis( i18n(
"<b>Start in debugger</b><p>"
00179
"Starts the debugger with the project's main "
00180
"executable. You may set some breakpoints "
00181
"before this, or you can interrupt the program "
00182
"while it is running, in order to get information "
00183
"about variables, frame stack, and so on.") );
00184
00185 action =
new KAction(i18n(
"Sto&p"),
"stop", 0,
00186
this, SLOT(slotStop()),
00187 actionCollection(),
"debug_stop");
00188 action->setToolTip( i18n(
"Stop debugger") );
00189 action->setWhatsThis(i18n(
"<b>Stop debugger</b><p>Kills the executable and exits the debugger."));
00190
00191 action =
new KAction(i18n(
"Interrupt"),
"player_pause", 0,
00192
this, SLOT(slotPause()),
00193 actionCollection(),
"debug_pause");
00194 action->setToolTip( i18n(
"Interrupt application") );
00195 action->setWhatsThis(i18n(
"<b>Interrupt application</b><p>Interrupts the debugged process or current GDB command."));
00196
00197 action =
new KAction(i18n(
"Run to &Cursor"),
"dbgrunto", 0,
00198
this, SLOT(slotRunToCursor()),
00199 actionCollection(),
"debug_runtocursor");
00200 action->setToolTip( i18n(
"Run to cursor") );
00201 action->setWhatsThis(i18n(
"<b>Run to cursor</b><p>Continues execution until the cursor position is reached."));
00202
00203
00204 action =
new KAction(i18n(
"Step &Over"),
"dbgnext", 0,
00205
this, SLOT(slotStepOver()),
00206 actionCollection(),
"debug_stepover");
00207 action->setToolTip( i18n(
"Step over the next line") );
00208 action->setWhatsThis( i18n(
"<b>Step over</b><p>"
00209
"Executes one line of source in the current source file. "
00210
"If the source line is a call to a function the whole "
00211
"function is executed and the app will stop at the line "
00212
"following the function call.") );
00213
00214
00215 action =
new KAction(i18n(
"Step over Ins&truction"),
"dbgnextinst", 0,
00216
this, SLOT(slotStepOverInstruction()),
00217 actionCollection(),
"debug_stepoverinst");
00218 action->setToolTip( i18n(
"Step over instruction") );
00219 action->setWhatsThis(i18n(
"<b>Step over instruction</b><p>Steps over the next assembly instruction."));
00220
00221
00222 action =
new KAction(i18n(
"Step &Into"),
"dbgstep", 0,
00223
this, SLOT(slotStepInto()),
00224 actionCollection(),
"debug_stepinto");
00225 action->setToolTip( i18n(
"Step into the next statement") );
00226 action->setWhatsThis( i18n(
"<b>Step into</b><p>"
00227
"Executes exactly one line of source. If the source line "
00228
"is a call to a function then execution will stop after "
00229
"the function has been entered.") );
00230
00231
00232 action =
new KAction(i18n(
"Step into I&nstruction"),
"dbgstepinst", 0,
00233
this, SLOT(slotStepIntoInstruction()),
00234 actionCollection(),
"debug_stepintoinst");
00235 action->setToolTip( i18n(
"Step into instruction") );
00236 action->setWhatsThis(i18n(
"<b>Step into instruction</b><p>Steps into the next assembly instruction."));
00237
00238
00239 action =
new KAction(i18n(
"Step O&ut"),
"dbgstepout", 0,
00240
this, SLOT(slotStepOut()),
00241 actionCollection(),
"debug_stepout");
00242 action->setToolTip( i18n(
"Steps out of the current function") );
00243 action->setWhatsThis( i18n(
"<b>Step out</b><p>"
00244
"Executes the application until the currently executing "
00245
"function is completed. The debugger will then display "
00246
"the line after the original call to that function. If "
00247
"program execution is in the outermost frame (i.e. in "
00248
"main()) then this operation has no effect.") );
00249
00250
00251 action =
new KAction(i18n(
"Viewers"),
"dbgmemview", 0,
00252
this, SLOT(slotMemoryView()),
00253 actionCollection(),
"debug_memview");
00254 action->setToolTip( i18n(
"Debugger viewers") );
00255 action->setWhatsThis(i18n(
"<b>Debugger viewers</b><p>Various information about application being executed. There are 4 views available:<br>"
00256
"<b>Memory</b><br>"
00257
"<b>Disassemble</b><br>"
00258
"<b>Registers</b><br>"
00259
"<b>Libraries</b>"));
00260
00261
00262 action =
new KAction(i18n(
"Examine Core File"),
"core", 0,
00263
this, SLOT(slotExamineCore()),
00264 actionCollection(),
"debug_core");
00265 action->setToolTip( i18n(
"Examine core file") );
00266 action->setWhatsThis( i18n(
"<b>Examine core file</b><p>"
00267
"This loads a core file, which is typically created "
00268
"after the application has crashed, e.g. with a "
00269
"segmentation fault. The core file contains an "
00270
"image of the program memory at the time it crashed, "
00271
"allowing you to do a post-mortem analysis.") );
00272
00273
00274 action =
new KAction(i18n(
"Attach to Process"),
"connect_creating", 0,
00275
this, SLOT(slotAttachProcess()),
00276 actionCollection(),
"debug_attach");
00277 action->setToolTip( i18n(
"Attach to process") );
00278 action->setWhatsThis(i18n(
"<b>Attach to process</b><p>Attaches the debugger to a running process."));
00279
00280 action =
new KAction(i18n(
"Toggle Breakpoint"), 0, 0,
00281
this, SLOT(toggleBreakpoint()),
00282 actionCollection(),
"debug_toggle_breakpoint");
00283 action->setToolTip(i18n(
"Toggle breakpoint"));
00284 action->setWhatsThis(i18n(
"<b>Toggle breakpoint</b><p>Toggles the breakpoint at the current line in editor."));
00285
00286 connect( mainWindow()->
main()->guiFactory(), SIGNAL(clientAdded(
KXMLGUIClient*)),
00287
this, SLOT(guiClientAdded(
KXMLGUIClient*)) );
00288
00289 connect( core(), SIGNAL(projectConfigWidget(
KDialogBase*)),
00290
this, SLOT(projectConfigWidget(
KDialogBase*)) );
00291
00292 connect( partController(), SIGNAL(loadedFile(
const QString &)),
00293 gdbBreakpointWidget, SLOT(slotRefreshBP(
const QString &)) );
00294 connect( debugger(), SIGNAL(toggledBreakpoint(
const QString &,
int)),
00295 gdbBreakpointWidget, SLOT(slotToggleBreakpoint(
const QString &,
int)) );
00296 connect( debugger(), SIGNAL(editedBreakpoint(
const QString &,
int)),
00297 gdbBreakpointWidget, SLOT(slotEditBreakpoint(
const QString &,
int)) );
00298 connect( debugger(), SIGNAL(toggledBreakpointEnabled(
const QString &,
int)),
00299 gdbBreakpointWidget, SLOT(slotToggleBreakpointEnabled(
const QString &,
int)) );
00300
00301 connect( core(), SIGNAL(contextMenu(
QPopupMenu *,
const Context *)),
00302
this, SLOT(contextMenu(
QPopupMenu *,
const Context *)) );
00303
00304 connect( core(), SIGNAL(stopButtonClicked(
KDevPlugin*)),
00305
this, SLOT(slotStop(
KDevPlugin*)) );
00306 connect( core(), SIGNAL(projectClosed()),
00307
this, SLOT(projectClosed()) );
00308
00309 connect( partController(), SIGNAL(activePartChanged(
KParts::Part*)),
00310
this, SLOT(slotActivePartChanged(
KParts::Part*)) );
00311
00312 procLineMaker =
new ProcessLineMaker();
00313
00314 connect( procLineMaker, SIGNAL(receivedStdoutLine(
const QString&)),
00315 appFrontend(), SLOT(insertStdoutLine(
const QString&)) );
00316 connect( procLineMaker, SIGNAL(receivedStderrLine(
const QString&)),
00317 appFrontend(), SLOT(insertStderrLine(
const QString&)) );
00318
00319 setupController();
00320
00321 QCStringList objects = kapp->dcopClient()->registeredApplications();
00322
for (QCStringList::Iterator it = objects.begin(); it != objects.end(); ++it)
00323
if ((*it).find(
"drkonqi-") == 0)
00324 slotDCOPApplicationRegistered(*it);
00325
00326 connect(kapp->dcopClient(), SIGNAL(applicationRegistered(
const QCString&)), SLOT(slotDCOPApplicationRegistered(
const QCString&)));
00327 kapp->dcopClient()->setNotifications(
true);
00328 }
00329
00330 void DebuggerPart::slotDCOPApplicationRegistered(
const QCString& appId)
00331 {
00332
if (appId.find(
"drkonqi-") == 0) {
00333
QByteArray answer;
00334
QCString replyType;
00335
00336
#if defined(KDE_MAKE_VERSION)
00337
# if KDE_VERSION >= KDE_MAKE_VERSION(3,1,90)
00338
kapp->dcopClient()->call(appId,
"krashinfo",
"appName()",
QByteArray(), replyType, answer,
true, 5000);
00339
# else
00340
kapp->dcopClient()->call(appId,
"krashinfo",
"appName()",
QByteArray(), replyType, answer,
true);
00341
# endif
00342
#else
00343
kapp->dcopClient()->call(appId,
"krashinfo",
"appName()",
QByteArray(), replyType, answer,
true);
00344
#endif
00345
00346
QDataStream d(answer, IO_ReadOnly);
00347
QCString appName;
00348 d >> appName;
00349
00350
if (appName.length() &&
project() &&
project()->
mainProgram().endsWith(appName)) {
00351 kapp->dcopClient()->send(appId,
"krashinfo",
"registerDebuggingApplication(QString)", i18n(
"Debug in &KDevelop"));
00352 connectDCOPSignal(appId,
"krashinfo",
"acceptDebuggingApplication()",
"slotDebugExternalProcess()",
true);
00353 }
00354 }
00355 }
00356
00357 ASYNC DebuggerPart::slotDebugExternalProcess()
00358 {
00359
QByteArray answer;
00360
QCString replyType;
00361
00362
#if defined(KDE_MAKE_VERSION)
00363
# if KDE_VERSION >= KDE_MAKE_VERSION(3,1,90)
00364
kapp->dcopClient()->call(kapp->dcopClient()->senderId(),
"krashinfo",
"pid()",
QByteArray(), replyType, answer,
true, 5000);
00365
# else
00366
kapp->dcopClient()->call(kapp->dcopClient()->senderId(),
"krashinfo",
"pid()",
QByteArray(), replyType, answer,
true);
00367
# endif
00368
#else
00369
kapp->dcopClient()->call(kapp->dcopClient()->senderId(),
"krashinfo",
"pid()",
QByteArray(), replyType, answer,
true);
00370
#endif
00371
00372
QDataStream d(answer, IO_ReadOnly);
00373
int pid;
00374 d >> pid;
00375
00376
if (
attachProcess(pid) &&
m_drkonqi.isEmpty()) {
00377
m_drkonqi = kapp->dcopClient()->senderId();
00378 QTimer::singleShot(15000,
this, SLOT(
slotCloseDrKonqi()));
00379
mainWindow()->
raiseView(
framestackWidget);
00380 }
00381
00382
mainWindow()->
main()->raise();
00383 }
00384
00385 void DebuggerPart::slotCloseDrKonqi()
00386 {
00387 kapp->dcopClient()->send(
m_drkonqi,
"MainApplication-Interface",
"quit()",
QByteArray());
00388
m_drkonqi =
"";
00389 }
00390
00391 DebuggerPart::~DebuggerPart()
00392 {
00393 kapp->dcopClient()->setNotifications(
false);
00394
00395
if (
variableWidget)
00396
mainWindow()->
removeView(
variableWidget);
00397
if (
gdbBreakpointWidget)
00398
mainWindow()->
removeView(
gdbBreakpointWidget);
00399
if (
framestackWidget)
00400
mainWindow()->
removeView(
framestackWidget);
00401
if (
disassembleWidget)
00402
mainWindow()->
removeView(
disassembleWidget);
00403
if(
gdbOutputWidget)
00404
mainWindow()->
removeView(
gdbOutputWidget);
00405
00406
delete variableWidget;
00407
delete gdbBreakpointWidget;
00408
delete framestackWidget;
00409
delete disassembleWidget;
00410
delete gdbOutputWidget;
00411
delete controller;
00412
delete floatingToolBar;
00413
delete statusBarIndicator;
00414
delete procLineMaker;
00415
00416 GDBParser::destroy();
00417 }
00418
00419
00420 void DebuggerPart::guiClientAdded(
KXMLGUIClient* client )
00421 {
00422
00423
00424
if( client ==
this )
00425 stateChanged(
QString(
"stopped") );
00426 }
00427
00428 void DebuggerPart::contextMenu(
QPopupMenu *popup,
const Context *context)
00429 {
00430
if (!context->
hasType( Context::EditorContext ))
00431
return;
00432
00433
const EditorContext *econtext = static_cast<const EditorContext*>(context);
00434
m_contextIdent = econtext->
currentWord();
00435
00436 popup->insertSeparator();
00437
if (econtext->
url().
isLocalFile())
00438 {
00439
int id = popup->insertItem( i18n(
"Toggle Breakpoint"),
this, SLOT(
toggleBreakpoint()) );
00440 popup->setWhatsThis(
id, i18n(
"<b>Toggle breakpoint</b><p>Toggles breakpoint at the current line."));
00441 }
00442
if (!
m_contextIdent.isEmpty())
00443 {
00444
int id = popup->insertItem( i18n(
"Watch: %1").arg(
m_contextIdent),
this, SLOT(
contextWatch()) );
00445 popup->setWhatsThis(
id, i18n(
"<b>Toggle breakpoint</b><p>Adds an expression under the cursor to the Variables/Watch list."));
00446 }
00447 }
00448
00449
00450 void DebuggerPart::toggleBreakpoint()
00451 {
00452
KParts::ReadWritePart *rwpart
00453 = dynamic_cast<KParts::ReadWritePart*>(
partController()->
activePart());
00454
KTextEditor::ViewCursorInterface *cursorIface
00455 = dynamic_cast<KTextEditor::ViewCursorInterface*>(
partController()->
activeWidget());
00456
00457
if (!rwpart || !cursorIface)
00458
return;
00459
00460 uint line, col;
00461 cursorIface->
cursorPositionReal(&line, &col);
00462
00463
gdbBreakpointWidget->slotToggleBreakpoint(rwpart->
url().
path(), line);
00464 }
00465
00466
00467 void DebuggerPart::contextWatch()
00468 {
00469
variableWidget->slotAddWatchVariable(
m_contextIdent);
00470 }
00471
00472
00473 void DebuggerPart::projectConfigWidget(
KDialogBase *dlg)
00474 {
00475
QVBox *vbox = dlg->
addVBoxPage(i18n(
"Debugger"));
00476
DebuggerConfigWidget *w =
new DebuggerConfigWidget(
this, vbox,
"debugger config widget");
00477 connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) );
00478 connect( dlg, SIGNAL(finished()),
controller, SLOT(configure()) );
00479 }
00480
00481
00482 void DebuggerPart::setupController()
00483 {
00484
VariableTree *variableTree =
variableWidget->varTree();
00485
00486
controller =
new GDBController(variableTree,
framestackWidget, *
projectDom());
00487
00488
00489 connect( variableTree, SIGNAL(expandItem(
TrimmableItem*)),
00490
controller, SLOT(slotExpandItem(
TrimmableItem*)));
00491 connect( variableTree, SIGNAL(expandUserItem(
VarItem*,
const QCString&)),
00492
controller, SLOT(slotExpandUserItem(
VarItem*,
const QCString&)));
00493 connect( variableTree, SIGNAL(setLocalViewState(
bool)),
00494
controller, SLOT(slotSetLocalViewState(
bool)));
00495 connect( variableTree, SIGNAL(varItemConstructed(
VarItem*)),
00496
controller, SLOT(slotVarItemConstructed(
VarItem*)));
00497
00498
00499 connect( variableTree, SIGNAL(toggleWatchpoint(
const QString &)),
00500
gdbBreakpointWidget, SLOT(slotToggleWatchpoint(
const QString &)));
00501
00502
00503 connect(
framestackWidget, SIGNAL(selectFrame(
int,
int,
bool)),
00504
controller, SLOT(slotSelectFrame(
int,
int,
bool)));
00505
00506
00507 connect(
gdbBreakpointWidget, SIGNAL(clearAllBreakpoints()),
00508
controller, SLOT(slotClearAllBreakpoints()));
00509 connect(
gdbBreakpointWidget, SIGNAL(publishBPState(
const Breakpoint&)),
00510
controller, SLOT(slotBPState(
const Breakpoint &)));
00511
00512
00513 connect(
disassembleWidget, SIGNAL(disassemble(
const QString&,
const QString&)),
00514
controller, SLOT(slotDisassemble(
const QString&,
const QString&)));
00515
00516
00517 connect(
gdbOutputWidget, SIGNAL(userGDBCmd(
const QString &)),
00518
controller, SLOT(slotUserGDBCmd(
const QString&)));
00519 connect(
gdbOutputWidget, SIGNAL(breakInto()),
00520
controller, SLOT(slotBreakInto()));
00521
00522
00523 connect(
controller, SIGNAL(acceptPendingBPs()),
00524
gdbBreakpointWidget, SLOT(slotSetPendingBPs()));
00525 connect(
controller, SIGNAL(unableToSetBPNow(
int)),
00526
gdbBreakpointWidget, SLOT(slotUnableToSetBPNow(
int)));
00527 connect(
controller, SIGNAL(rawGDBBreakpointList (
char*)),
00528
gdbBreakpointWidget, SLOT(slotParseGDBBrkptList(
char*)));
00529 connect(
controller, SIGNAL(rawGDBBreakpointSet(
char*,
int)),
00530
gdbBreakpointWidget, SLOT(slotParseGDBBreakpointSet(
char*,
int)));
00531
00532
00533 connect(
controller, SIGNAL(showStepInSource(
const QString&,
int,
const QString&)),
00534
disassembleWidget, SLOT(slotShowStepInSource(
const QString&,
int,
const QString&)));
00535 connect(
controller, SIGNAL(rawGDBDisassemble(
char*)),
00536
disassembleWidget, SLOT(slotDisassemble(
char*)));
00537
00538
00539 connect(
controller, SIGNAL(dbgStatus(
const QString&,
int)),
00540
this, SLOT(
slotStatus(
const QString&,
int)));
00541 connect(
controller, SIGNAL(showStepInSource(
const QString&,
int,
const QString&)),
00542
this, SLOT(
slotShowStep(
const QString&,
int)));
00543
00544
00545 connect(
controller, SIGNAL(ttyStdout(
const char*)),
00546
procLineMaker, SLOT(slotReceivedStdout(
const char*)));
00547 connect(
controller, SIGNAL(ttyStderr(
const char*)),
00548
procLineMaker, SLOT(slotReceivedStderr(
const char*)));
00549
00550
00551 connect(
controller, SIGNAL(gdbStdout(
const char*)),
00552
gdbOutputWidget, SLOT(slotReceivedStdout(
const char*)) );
00553 connect(
controller, SIGNAL(gdbStderr(
const char*)),
00554
gdbOutputWidget, SLOT(slotReceivedStderr(
const char*)) );
00555 connect(
controller, SIGNAL(dbgStatus(
const QString&,
int)),
00556
gdbOutputWidget, SLOT(slotDbgStatus(
const QString&,
int)));
00557
00558
00559 connect(
gdbBreakpointWidget, SIGNAL(publishBPState(
const Breakpoint&)),
00560
disassembleWidget, SLOT(slotBPState(
const Breakpoint &)));
00561 }
00562
00563
00564 bool DebuggerPart::startDebugger()
00565 {
00566
QString build_dir;
00567
DomUtil::PairList run_envvars;
00568
QString run_directory;
00569
QString program;
00570
QString run_arguments;
00571
00572
if (
project()) {
00573 build_dir =
project()->
buildDirectory();
00574 run_envvars =
project()->
runEnvironmentVars();
00575 run_directory =
project()->
runDirectory();
00576 program =
project()->
mainProgram();
00577 run_arguments =
project()->
runArguments();
00578 }
00579
00580
QString shell = DomUtil::readEntry(*
projectDom(),
"/kdevdebugger/general/dbgshell");
00581
if( !shell.isEmpty() )
00582 {
00583
QFileInfo info( shell );
00584
if( info.isRelative() )
00585 {
00586 shell = build_dir +
"/" + shell;
00587 info.setFile( shell );
00588 }
00589
if( !info.exists() )
00590 {
00591 KMessageBox::error(
00592
mainWindow()->
main(),
00593 i18n(
"Could not locate the debugging shell '%1'.").arg( shell ),
00594 i18n(
"Debugging shell not found.") );
00595
return false;
00596 }
00597 }
00598
00599
core()->
running(
this,
true);
00600
00601 stateChanged(
QString(
"active") );
00602
00603
KActionCollection *ac =
actionCollection();
00604 ac->
action(
"debug_run")->
setText( i18n(
"&Continue") );
00605 ac->
action(
"debug_run")->
setIcon(
"dbgrun" );
00606 ac->
action(
"debug_run")->
setStatusText( i18n(
"Continues the application execution") );
00607 ac->
action(
"debug_run")->
setWhatsThis( i18n(
"Continue application execution\n\n"
00608
"Continues the execution of your application in the "
00609
"debugger. This only takes effect when the application "
00610
"has been halted by the debugger (i.e. a breakpoint has "
00611
"been activated or the interrupt was pressed).") );
00612
00613
00614
mainWindow()->
setViewAvailable(
variableWidget,
true);
00615
mainWindow()->
setViewAvailable(
framestackWidget,
true);
00616
mainWindow()->
setViewAvailable(
disassembleWidget,
true);
00617
mainWindow()->
setViewAvailable(
gdbOutputWidget,
true);
00618
00619
variableWidget->setEnabled(
true);
00620
framestackWidget->setEnabled(
true);
00621
disassembleWidget->setEnabled(
true);
00622
00623
gdbOutputWidget->clear();
00624
gdbOutputWidget->setEnabled(
true);
00625
00626
if (DomUtil::readBoolEntry(*
projectDom(),
"/kdevdebugger/general/floatingtoolbar",
true))
00627 {
00628
floatingToolBar =
new DbgToolBar(
this,
mainWindow()->
main());
00629
floatingToolBar->show();
00630 }
00631
00632
controller->
slotStart(shell, run_envvars, run_directory, program, run_arguments);
00633
return true;
00634 }
00635
00636 void DebuggerPart::slotStopDebugger()
00637 {
00638
controller->
slotStopDebugger();
00639
debugger()->
clearExecutionPoint();
00640
00641
delete floatingToolBar;
00642
floatingToolBar = 0;
00643
00644
gdbBreakpointWidget->reset();
00645
framestackWidget->clear();
00646
variableWidget->clear();
00647
disassembleWidget->clear();
00648
disassembleWidget->slotActivate(
false);
00649
00650
variableWidget->setEnabled(
false);
00651
framestackWidget->setEnabled(
false);
00652
disassembleWidget->setEnabled(
false);
00653
gdbOutputWidget->setEnabled(
false);
00654
00655
mainWindow()->
setViewAvailable(
variableWidget,
false);
00656
mainWindow()->
setViewAvailable(
framestackWidget,
false);
00657
mainWindow()->
setViewAvailable(
disassembleWidget,
false);
00658
mainWindow()->
setViewAvailable(
gdbOutputWidget,
false);
00659
00660
KActionCollection *ac =
actionCollection();
00661 ac->
action(
"debug_run")->
setText( i18n(
"&Start") );
00662 ac->
action(
"debug_run")->
setIcon(
"1rightarrow" );
00663 ac->
action(
"debug_run")->
setStatusText( i18n(
"Runs the program in the debugger") );
00664 ac->
action(
"debug_run")->
setWhatsThis( i18n(
"Start in debugger\n\n"
00665
"Starts the debugger with the project's main "
00666
"executable. You may set some breakpoints "
00667
"before this, or you can interrupt the program "
00668
"while it is running, in order to get information "
00669
"about variables, frame stack, and so on.") );
00670
00671 stateChanged(
QString(
"stopped") );
00672
00673
core()->
running(
this,
false);
00674 }
00675
00676 void DebuggerPart::projectClosed()
00677 {
00678
slotStopDebugger();
00679 }
00680
00681 void DebuggerPart::slotRun()
00682 {
00683
if(
controller->
stateIsOn(
s_dbgNotStarted ) )
00684 {
00685
mainWindow()->
statusBar()->message(i18n(
"Debugging program"), 1000);
00686
mainWindow()->
raiseView(
gdbOutputWidget);
00687
appFrontend()->
clearView();
00688
startDebugger();
00689 }
00690
else
00691 {
00692
mainWindow()->
statusBar()->message(i18n(
"Continuing program"), 1000);
00693 }
00694
controller->
slotRun();
00695 }
00696
00697
00698 void DebuggerPart::slotExamineCore()
00699 {
00700
mainWindow()->
statusBar()->message(i18n(
"Choose a core file to examine..."), 1000);
00701
00702
QString dirName =
project()?
project()->
projectDirectory() : QDir::homeDirPath();
00703
QString coreFile = KFileDialog::getOpenFileName(dirName);
00704
if (coreFile.isNull())
00705
return;
00706
00707
mainWindow()->
statusBar()->message(i18n(
"Examining core file %1").arg(coreFile), 1000);
00708
00709
startDebugger();
00710
controller->
slotCoreFile(coreFile);
00711 }
00712
00713
00714 void DebuggerPart::slotAttachProcess()
00715 {
00716
mainWindow()->
statusBar()->message(i18n(
"Choose a process to attach to..."), 1000);
00717
00718
Dbg_PS_Dialog dlg;
00719
if (!dlg.exec() || !dlg.
pidSelected())
00720
return;
00721
00722
int pid = dlg.
pidSelected();
00723
attachProcess(pid);
00724 }
00725
00726 bool DebuggerPart::attachProcess(
int pid)
00727 {
00728
mainWindow()->
statusBar()->message(i18n(
"Attaching to process %1").arg(pid), 1000);
00729
00730
bool ret =
startDebugger();
00731
controller->
slotAttachTo(pid);
00732
return ret;
00733 }
00734
00735
00736 void DebuggerPart::slotStop(
KDevPlugin* which)
00737 {
00738
if( which != 0 && which !=
this )
00739
return;
00740
00741
00742
slotStopDebugger();
00743 }
00744
00745
00746 void DebuggerPart::slotPause()
00747 {
00748
controller->
slotBreakInto();
00749 }
00750
00751
00752 void DebuggerPart::slotRunToCursor()
00753 {
00754
KParts::ReadWritePart *rwpart
00755 = dynamic_cast<KParts::ReadWritePart*>(
partController()->
activePart());
00756
KTextEditor::ViewCursorInterface *cursorIface
00757 = dynamic_cast<KTextEditor::ViewCursorInterface*>(
partController()->
activeWidget());
00758
00759
if (!rwpart || !rwpart->
url().
isLocalFile() || !cursorIface)
00760
return;
00761
00762 uint line, col;
00763 cursorIface->
cursorPosition(&line, &col);
00764
00765
controller->
slotRunUntil(rwpart->
url().
path(), line);
00766 }
00767
00768 void DebuggerPart::slotStepOver()
00769 {
00770
controller->
slotStepOver();
00771 }
00772
00773
00774 void DebuggerPart::slotStepOverInstruction()
00775 {
00776
controller->
slotStepOver();
00777 }
00778
00779
00780 void DebuggerPart::slotStepIntoInstruction()
00781 {
00782
controller->
slotStepIntoIns();
00783 }
00784
00785
00786 void DebuggerPart::slotStepInto()
00787 {
00788
controller->
slotStepInto();
00789 }
00790
00791
00792 void DebuggerPart::slotStepOut()
00793 {
00794
controller->
slotStepOutOff();
00795 }
00796
00797
00798 void DebuggerPart::slotMemoryView()
00799 {
00800
00801
00802
MemoryViewDialog *dlg =
new MemoryViewDialog();
00803 connect( dlg, SIGNAL(disassemble(
const QString&,
const QString&)),
00804
controller, SLOT(slotDisassemble(
const QString&,
const QString&)));
00805 connect( dlg, SIGNAL(memoryDump(
const QString&,
const QString&)),
00806
controller, SLOT(slotMemoryDump(
const QString&,
const QString&)));
00807 connect( dlg, SIGNAL(registers()),
00808
controller, SLOT(slotRegisters()));
00809 connect( dlg, SIGNAL(libraries()),
00810
controller, SLOT(slotLibraries()));
00811
00812 connect(
controller, SIGNAL(rawGDBMemoryDump(
char*)),
00813 dlg, SLOT(slotRawGDBMemoryView(
char*)));
00814 connect(
controller, SIGNAL(rawGDBDisassemble(
char*)),
00815 dlg, SLOT(slotRawGDBMemoryView(
char*)));
00816 connect(
controller, SIGNAL(rawGDBRegisters(
char*)),
00817 dlg, SLOT(slotRawGDBMemoryView(
char*)));
00818 connect(
controller, SIGNAL(rawGDBLibraries(
char*)),
00819 dlg, SLOT(slotRawGDBMemoryView(
char*)));
00820
00821 dlg->exec();
00822
delete dlg;
00823 }
00824
00825
00826 void DebuggerPart::slotRefreshBPState(
const Breakpoint& BP)
00827 {
00828
if (BP.
type() ==
BP_TYPE_FilePos)
00829 {
00830
const FilePosBreakpoint& bp = dynamic_cast<const FilePosBreakpoint&>(BP);
00831
if (bp.
isActionDie())
00832
debugger()->
setBreakpoint(bp.
fileName(), bp.
lineNum()-1, -1,
true,
false);
00833
else
00834
debugger()->
setBreakpoint(bp.
fileName(), bp.
lineNum()-1,
00835 1, bp.
isEnabled(), bp.
isPending() );
00836 }
00837 }
00838
00839
00840 void DebuggerPart::slotStatus(
const QString &msg,
int state)
00841 {
00842
QString stateIndicator;
00843
00844
if (state &
s_dbgNotStarted)
00845 {
00846 stateIndicator =
" ";
00847 }
00848
else if (state &
s_appBusy)
00849 {
00850 stateIndicator =
"A";
00851
debugger()->
clearExecutionPoint();
00852 stateChanged(
QString(
"active") );
00853 }
00854
else if (state &
s_programExited)
00855 {
00856 stateIndicator =
"E";
00857 stateChanged(
QString(
"stopped") );
00858
KActionCollection *ac =
actionCollection();
00859 ac->
action(
"debug_run")->
setText( i18n(
"Restart") );
00860 ac->
action(
"debug_run")->
setIcon(
"1rightarrow" );
00861 ac->
action(
"debug_run")->
setStatusText( i18n(
"Restart the program in the debugger") );
00862 ac->
action(
"debug_run")->
setWhatsThis( i18n(
"Restart in debugger\n\n"
00863
"Restarts the program in the debugger") );
00864
00865 }
00866
else
00867 {
00868 stateIndicator =
"P";
00869 stateChanged(
QString(
"paused") );
00870 }
00871
00872
00873
kdDebug(9012) <<
"Debugger state: " << stateIndicator <<
": " <<
endl;
00874
kdDebug(9012) <<
" " << msg <<
endl;
00875
00876
statusBarIndicator->setText(stateIndicator);
00877
if (!msg.isEmpty())
00878
mainWindow()->
statusBar()->message(msg, 3000);
00879 }
00880
00881
00882 void DebuggerPart::slotShowStep(
const QString &fileName,
int lineNum)
00883 {
00884
if ( ! fileName.isEmpty() )
00885 {
00886
00887
debugger()->
gotoExecutionPoint(fileName, lineNum-1);
00888 }
00889 }
00890
00891
00892 void DebuggerPart::slotGotoSource(
const QString &fileName,
int lineNum)
00893 {
00894
if ( ! fileName.isEmpty() )
00895
partController()->
editDocument(fileName, lineNum);
00896 }
00897
00898
00899 void DebuggerPart::slotActivePartChanged(
KParts::Part* part )
00900 {
00901
KAction* action =
actionCollection()->
action(
"debug_toggle_breakpoint");
00902
if(!action)
00903
return;
00904
00905
if(!part)
00906 {
00907 action->setEnabled(
false);
00908
return;
00909 }
00910
KTextEditor::ViewCursorInterface *iface
00911 = dynamic_cast<KTextEditor::ViewCursorInterface*>(part->
widget());
00912 action->setEnabled( iface != 0 );
00913 }
00914
00915 void DebuggerPart::restorePartialProjectSession(
const QDomElement* el)
00916 {
00917
gdbBreakpointWidget->restorePartialProjectSession(el);
00918 }
00919
00920 void DebuggerPart::savePartialProjectSession(
QDomElement* el)
00921 {
00922
gdbBreakpointWidget->savePartialProjectSession(el);
00923 }
00924
00925 }
00926
00927
#include "debuggerpart.moc"