00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "javadebuggerpart.h"
00015
00016 #include <qdir.h>
00017 #include <qwhatsthis.h>
00018 #include <kfiledialog.h>
00019 #include <kdebug.h>
00020 #include <kiconloader.h>
00021 #include <klocale.h>
00022 #include <kaction.h>
00023 #include <kstatusbar.h>
00024
00025 #include "kdevcore.h"
00026 #include "kdevproject.h"
00027 #include "kdevmainwindow.h"
00028 #include "kdevpartcontroller.h"
00029 #include "kdevdebugger.h"
00030
00031 #include "variablewidget.h"
00032 #include "breakpointwidget.h"
00033 #include "framestackwidget.h"
00034 #include "disassemblewidget.h"
00035 #include "jdbcontroller.h"
00036 #include "breakpoint.h"
00037 #include "dbgpsdlg.h"
00038 #include "memviewdlg.h"
00039
00040
00041 namespace JAVADebugger
00042 {
00043 static const KAboutData data("kdevjavadebugger", I18N_NOOP("Debugger"), "1.0");
00044 K_EXPORT_COMPONENT_FACTORY( libkdevjavadebugger, JavaDebuggerFactory( &data ) )
00045
00046 JavaDebuggerPart::JavaDebuggerPart(QObject *parent, const char *name, const QStringList &)
00047 : KDevPlugin("JavaDebugger", "debugger", parent, name ? name : "JavaDebuggerPart"),
00048 controller(0)
00049 {
00050 setInstance(JavaDebuggerFactory::instance());
00051
00052 setXMLFile("kdevjavadebugger.rc");
00053
00054
00055
00056
00057
00058 variableWidget = new VariableWidget();
00059 variableWidget->setEnabled(false);
00060 variableWidget->setIcon(SmallIcon("math_brace"));
00061 variableWidget->setCaption(i18n("Variable Tree"));
00062 QWhatsThis::add(variableWidget, i18n("Variable tree\n\n"
00063 "The variable tree allows you to see "
00064 "the variable values as you step "
00065 "through your program using the internal "
00066 "debugger. Click the right mouse button on items in "
00067 "this view to get a popup menu.\n"
00068 "To speed up stepping through your code "
00069 "leave the tree items closed and add the "
00070 "variable(s) to the watch section.\n"
00071 "To change a variable value in your "
00072 "running app use a watch variable (⪚ a=5)."));
00073 mainWindow()->embedSelectView(variableWidget, i18n("Watch"), i18n("debugger variable-view"));
00074 mainWindow()->setViewAvailable(variableWidget, false);
00075
00076 breakpointWidget = new BreakpointWidget();
00077 breakpointWidget->setCaption(i18n("Breakpoint List"));
00078 QWhatsThis::add(breakpointWidget, i18n("Breakpoint list\n\n"
00079 "Displays a list of breakpoints with "
00080 "their current status. Clicking on a "
00081 "breakpoint item with the right mouse button displays "
00082 "a popup menu so you may manipulate the "
00083 "breakpoint. Double clicking will take you "
00084 "to the source in the editor window."));
00085 mainWindow()->embedOutputView(breakpointWidget, i18n("&Breakpoints"), i18n("debugger breakpoints"));
00086
00087 framestackWidget = new FramestackWidget();
00088 framestackWidget->setEnabled(false);
00089 framestackWidget->setCaption(i18n("Frame Stack"));
00090 QWhatsThis::add(framestackWidget, i18n("Frame stack\n\n"
00091 "Often referred to as the \"call stack\", "
00092 "this is a list showing what function is "
00093 "currently active and who called each "
00094 "function to get to this point in your "
00095 "program. By clicking on an item you "
00096 "can see the values in any of the "
00097 "previous calling functions."));
00098 mainWindow()->embedOutputView(framestackWidget, i18n("&Frame Stack"), i18n("debugger function call stack"));
00099 mainWindow()->setViewAvailable(framestackWidget, false);
00100
00101 disassembleWidget = new DisassembleWidget();
00102 disassembleWidget->setEnabled(false);
00103 disassembleWidget->setCaption(i18n("Machine Code Display"));
00104 QWhatsThis::add(disassembleWidget, i18n("Machine code display\n\n"
00105 "A machine code view into your running "
00106 "executable with the current instruction "
00107 "highlighted. You can step instruction by "
00108 "instruction using the debuggers toolbar "
00109 "buttons of \"step over\" instruction and "
00110 "\"step into\" instruction."));
00111 mainWindow()->embedOutputView(disassembleWidget, i18n("Disassemble"), i18n("debugger disassemble"));
00112 mainWindow()->setViewAvailable(disassembleWidget, false);
00113
00114 VariableTree *variableTree = variableWidget->varTree();
00115
00116
00117 connect( variableTree, SIGNAL(selectFrame(int)),
00118 framestackWidget, SLOT(slotSelectFrame(int)));
00119
00120
00121 connect( breakpointWidget, SIGNAL(refreshBPState(Breakpoint*)),
00122 this, SLOT(slotRefreshBPState(Breakpoint*)));
00123 connect( breakpointWidget, SIGNAL(publishBPState(Breakpoint*)),
00124 this, SLOT(slotRefreshBPState(Breakpoint*)));
00125 connect( breakpointWidget, SIGNAL(gotoSourcePosition(const QString&, int)),
00126 this, SLOT(slotGotoSource(const QString&, int)) );
00127
00128
00129
00130
00131
00132 KAction *action;
00133
00134 action = new KAction(i18n("&Start"), "1rightarrow", 0,
00135 this, SLOT(slotRun()),
00136 actionCollection(), "debug_run");
00137 action->setStatusText( i18n("Runs the program in the debugger") );
00138 action->setWhatsThis( i18n("Start in debugger\n\n"
00139 "Starts the debugger with the project's main "
00140 "executable. You may set some breakpoints "
00141 "before this, or you can interrupt the program "
00142 "while it is running, in order to get information "
00143 "about variables, frame stack, and so on.") );
00144
00145 action = new KAction(i18n("Sto&p"), "stop", 0,
00146 this, SLOT(slotStop()),
00147 actionCollection(), "debug_stop");
00148 action->setEnabled(false);
00149 action->setStatusText( i18n("Kills the executable and exits the debugger") );
00150
00151 action = new KAction(i18n("Interrupt"), "player_pause", 0,
00152 this, SLOT(slotPause()),
00153 actionCollection(), "debug_pause");
00154 action->setEnabled(false);
00155 action->setStatusText( i18n("Interrupts the application") );
00156
00157 action = new KAction(i18n("&Continue"), "dbgrun", 0,
00158 this, SLOT(slotContinue()),
00159 actionCollection(), "debug_cont");
00160 action->setEnabled(false);
00161 action->setStatusText( i18n("Continues the application execution") );
00162 action->setWhatsThis( i18n("Continue application execution\n\n"
00163 "Continues the execution of your application in the "
00164 "debugger. This only takes effect when the application "
00165 "has been halted by the debugger (i.e. a breakpoint has "
00166 "been activated or the interrupt was pressed).") );
00167
00168 action = new KAction(i18n("Step &Over"), "dbgnext", 0,
00169 this, SLOT(slotStepOver()),
00170 actionCollection(), "debug_stepover");
00171 action->setEnabled(false);
00172 action->setStatusText( i18n("Steps over the next line") );
00173 action->setWhatsThis( i18n("Step over\n\n"
00174 "Executes one line of source in the current source file. "
00175 "If the source line is a call to a function the whole "
00176 "function is executed and the app will stop at the line "
00177 "following the function call.") );
00178
00179 action = new KAction(i18n("Step &Into"), "dbgstep", 0,
00180 this, SLOT(slotStepInto()),
00181 actionCollection(), "debug_stepinto");
00182 action->setEnabled(false);
00183 action->setStatusText( i18n("Steps into the next statement") );
00184 action->setWhatsThis( i18n("Step into\n\n"
00185 "Executes exactly one line of source. If the source line "
00186 "is a call to a function then execution will stop after "
00187 "the function has been entered.") );
00188
00189 action = new KAction(i18n("Step into I&nstruction"), "dbgstepinst", 0,
00190 this, SLOT(slotStepIntoInstruction()),
00191 actionCollection(), "debug_stepintoinst");
00192 action->setEnabled(false);
00193 action->setStatusText( i18n("Steps into the next assembly instruction") );
00194
00195 action = new KAction(i18n("Step O&ut"), "dbgstepout", 0,
00196 this, SLOT(slotStepOut()),
00197 actionCollection(), "debug_stepout");
00198 action->setEnabled(false);
00199 action->setStatusText( i18n("Steps out of the current function") );
00200 action->setWhatsThis( i18n("Step out of\n\n"
00201 "Executes the application until the currently executing "
00202 "function is completed. The debugger will then display "
00203 "the line after the original call to that function. If "
00204 "we are in the outermost frame (i.e. in main()), then "
00205 "this operation has no effect.") );
00206
00207 action = new KAction(i18n("Viewers"), "dbgmemview", 0,
00208 this, SLOT(slotMemoryView()),
00209 actionCollection(), "debug_memview");
00210 action->setEnabled(false);
00211 action->setStatusText( i18n("Various views into the application") );
00212
00213 connect( core(), SIGNAL(toggledBreakpoint(const QString &, int)),
00214 breakpointWidget, SLOT(slotToggleBreakpoint(const QString &, int)) );
00215 connect( core(), SIGNAL(editedBreakpoint(const QString &, int)),
00216 breakpointWidget, SLOT(slotEditBreakpoint(const QString &, int)) );
00217 connect( core(), SIGNAL(toggledBreakpointEnabled(const QString &, int)),
00218 breakpointWidget, SLOT(slotToggleBreakpointEnabled(const QString &, int)) );
00219 }
00220
00221
00222 JavaDebuggerPart::~JavaDebuggerPart()
00223 {
00224 mainWindow()->removeView(variableWidget);
00225 mainWindow()->removeView(breakpointWidget);
00226 mainWindow()->removeView(framestackWidget);
00227 mainWindow()->removeView(disassembleWidget);
00228
00229 delete variableWidget;
00230 delete breakpointWidget;
00231 delete framestackWidget;
00232 delete disassembleWidget;
00233 delete controller;
00234
00235 }
00236
00237
00238 void JavaDebuggerPart::setupController()
00239 {
00240 VariableTree *variableTree = variableWidget->varTree();
00241
00242 if (project()) {
00243 controller = new JDBController(variableTree, framestackWidget, project()->projectDirectory(), project()->mainProgram());
00244 } else {
00245 controller = new JDBController(variableTree, framestackWidget, "", "");
00246 }
00247
00248
00249 connect( variableTree, SIGNAL(expandItem(VarItem*)),
00250 controller, SLOT(slotExpandItem(VarItem*)));
00251 connect( variableTree, SIGNAL(expandUserItem(VarItem*, const QCString&)),
00252 controller, SLOT(slotExpandUserItem(VarItem*, const QCString&)));
00253 connect( variableTree, SIGNAL(setLocalViewState(bool)),
00254 controller, SLOT(slotSetLocalViewState(bool)));
00255
00256
00257 connect( framestackWidget, SIGNAL(selectFrame(int)),
00258 controller, SLOT(slotSelectFrame(int)));
00259
00260
00261 connect( breakpointWidget, SIGNAL(clearAllBreakpoints()),
00262 controller, SLOT(slotClearAllBreakpoints()));
00263
00264
00265 connect( disassembleWidget,SIGNAL(disassemble(const QString&, const QString&)),
00266 controller, SLOT(slotDisassemble(const QString&, const QString&)));
00267
00268
00269 connect( controller, SIGNAL(acceptPendingBPs()),
00270 breakpointWidget, SLOT(slotSetPendingBPs()));
00271 connect( controller, SIGNAL(unableToSetBPNow(int)),
00272 breakpointWidget, SLOT(slotUnableToSetBPNow(int)));
00273 connect( controller, SIGNAL(rawJDBBreakpointList (char*)),
00274 breakpointWidget, SLOT(slotParseJDBBrkptList(char*)));
00275 connect( controller, SIGNAL(rawJDBBreakpointSet(char*, int)),
00276 breakpointWidget, SLOT(slotParseJDBBreakpointSet(char*, int)));
00277 connect( breakpointWidget, SIGNAL(publishBPState(Breakpoint*)),
00278 controller, SLOT(slotBPState(Breakpoint*)));
00279
00280
00281 connect( controller, SIGNAL(showStepInSource(const QString&, int, const QString&)),
00282 disassembleWidget,SLOT(slotShowStepInSource(const QString&, int, const QString&)));
00283 connect( controller, SIGNAL(rawJDBDisassemble(char*)),
00284 disassembleWidget,SLOT(slotDisassemble(char*)));
00285
00286
00287 connect( controller, SIGNAL(dbgStatus(const QString&, int)),
00288 this, SLOT(slotStatus(const QString&, int)));
00289 connect( controller, SIGNAL(showStepInSource(const QString&, int, const QString&)),
00290 this, SLOT(slotShowStep(const QString&, int)));
00291
00292
00293
00294 #if 0
00295 connect( controller, SIGNAL(ttyStdout(const char*)),
00296 this, SLOT(slotApplReceivedStdout(const char*)));
00297 connect( controller, SIGNAL(ttyStderr(const char*)),
00298 this, SLOT(slotApplReceivedStderr(const char*)));
00299 #endif
00300 }
00301
00302
00303 void JavaDebuggerPart::startDebugger()
00304 {
00305 core()->running(this, true);
00306
00307 KActionCollection *ac = actionCollection();
00308 ac->action("debug_stop")->setEnabled(true);
00309 ac->action("debug_pause")->setEnabled(true);
00310 ac->action("debug_cont")->setEnabled(true);
00311 ac->action("debug_stepover")->setEnabled(true);
00312 ac->action("debug_stepinto")->setEnabled(true);
00313 ac->action("debug_stepintoinst")->setEnabled(true);
00314 ac->action("debug_stepout")->setEnabled(true);
00315 ac->action("debug_memview")->setEnabled(true);
00316
00317 variableWidget->setEnabled(true);
00318 framestackWidget->setEnabled(true);
00319 disassembleWidget->setEnabled(true);
00320
00321 mainWindow()->setViewAvailable(variableWidget, true);
00322 mainWindow()->setViewAvailable(framestackWidget, true);
00323 mainWindow()->setViewAvailable(disassembleWidget, true);
00324
00325
00326
00327
00328
00329
00330
00331 setupController();
00332 controller->slotStart("", "", "");
00333 breakpointWidget->slotSetPendingBPs();
00334 }
00335
00336
00337 void JavaDebuggerPart::slotRun()
00338 {
00339 if (controller)
00340 slotStop();
00341
00342 mainWindow()->statusBar()->message(i18n("Debugging program"));
00343
00344 startDebugger();
00345 controller->slotRun();
00346 }
00347
00348
00349
00350 void JavaDebuggerPart::slotStop()
00351 {
00352 core()->running(this, false);
00353
00354 KActionCollection *ac = actionCollection();
00355 ac->action("debug_stop")->setEnabled(false);
00356 ac->action("debug_pause")->setEnabled(false);
00357 ac->action("debug_cont")->setEnabled(false);
00358 ac->action("debug_runtocursor")->setEnabled(false);
00359 ac->action("debug_stepover")->setEnabled(false);
00360 ac->action("debug_stepoverinst")->setEnabled(false);
00361 ac->action("debug_stepinto")->setEnabled(false);
00362 ac->action("debug_stepintoinst")->setEnabled(false);
00363 ac->action("debug_stepout")->setEnabled(false);
00364 ac->action("debug_memview")->setEnabled(false);
00365
00366 mainWindow()->setViewAvailable(variableWidget, false);
00367 mainWindow()->setViewAvailable(framestackWidget, false);
00368 mainWindow()->setViewAvailable(disassembleWidget, false);
00369
00370 variableWidget->setEnabled(false);
00371 framestackWidget->setEnabled(false);
00372 disassembleWidget->setEnabled(false);
00373
00374 breakpointWidget->reset();
00375 framestackWidget->clear();
00376 variableWidget->clear();
00377 disassembleWidget->clear();
00378 disassembleWidget->slotActivate(false);
00379
00380 debugger()->clearExecutionPoint();
00381
00382
00383
00384 }
00385
00386
00387 void JavaDebuggerPart::slotPause()
00388 {
00389 controller->slotBreakInto();
00390 }
00391
00392
00393 void JavaDebuggerPart::slotContinue()
00394 {
00395 controller->slotRun();
00396 }
00397
00398
00399 void JavaDebuggerPart::slotStepOver()
00400 {
00401 controller->slotStepOver();
00402 }
00403
00404
00405 void JavaDebuggerPart::slotStepIntoInstruction()
00406 {
00407 controller->slotStepIntoIns();
00408 }
00409
00410
00411 void JavaDebuggerPart::slotStepInto()
00412 {
00413 controller->slotStepInto();
00414 }
00415
00416
00417 void JavaDebuggerPart::slotStepOut()
00418 {
00419 controller->slotStepOutOff();
00420 }
00421
00422
00423 void JavaDebuggerPart::slotMemoryView()
00424 {
00425
00426
00427 MemoryViewDialog *dlg = new MemoryViewDialog();
00428 connect( dlg, SIGNAL(disassemble(const QString&, const QString&)),
00429 controller, SLOT(slotDisassemble(const QString&, const QString&)));
00430 connect( dlg, SIGNAL(memoryDump(const QString&, const QString&)),
00431 controller, SLOT(slotMemoryDump(const QString&, const QString&)));
00432 connect( dlg, SIGNAL(registers()),
00433 controller, SLOT(slotRegisters()));
00434 connect( dlg, SIGNAL(libraries()),
00435 controller, SLOT(slotLibraries()));
00436
00437 connect( controller, SIGNAL(rawJDBMemoryDump(char*)),
00438 dlg, SLOT(slotRawJDBMemoryView(char*)));
00439 connect( controller, SIGNAL(rawJDBDisassemble(char*)),
00440 dlg, SLOT(slotRawJDBMemoryView(char*)));
00441 connect( controller, SIGNAL(rawJDBRegisters(char*)),
00442 dlg, SLOT(slotRawJDBMemoryView(char*)));
00443 connect( controller, SIGNAL(rawJDBLibraries(char*)),
00444 dlg, SLOT(slotRawJDBMemoryView(char*)));
00445
00446 dlg->exec();
00447 delete dlg;
00448 }
00449
00450
00451 void JavaDebuggerPart::slotRefreshBPState(Breakpoint *BP)
00452 {
00453 if (BP->isActionDie())
00454 debugger()->setBreakpoint(BP->fileName(), BP->lineNum()-1,
00455 -1, true, false);
00456 else
00457 debugger()->setBreakpoint(BP->fileName(), BP->lineNum()-1,
00458 1, BP->isEnabled(), BP->isPending() );
00459 }
00460
00461
00462 void JavaDebuggerPart::slotStatus(const QString &msg, int state)
00463 {
00464 QString stateIndicator("P");
00465
00466 if (state & s_appBusy) {
00467 stateIndicator = "A";
00468 debugger()->clearExecutionPoint();
00469 }
00470
00471 if (state & (s_dbgNotStarted|s_appNotStarted))
00472 stateIndicator = " ";
00473
00474 if (state & s_programExited) {
00475 stateIndicator = "E";
00476 debugger()->clearExecutionPoint();
00477 }
00478
00479
00480 kdDebug(9012) << "Debugger state: " << stateIndicator << endl;
00481
00482 if (!msg.isEmpty())
00483 mainWindow()->statusBar()->message(msg);
00484 }
00485
00486
00487 void JavaDebuggerPart::slotShowStep(const QString &fileName, int lineNum)
00488 {
00489
00490 debugger()->gotoExecutionPoint(KURL( fileName ), lineNum-1);
00491 }
00492
00493
00494 void JavaDebuggerPart::slotGotoSource(const QString &fileName, int lineNum)
00495 {
00496 partController()->editDocument(KURL( fileName ), lineNum);
00497 }
00498
00499 }
00500
00501 #include "javadebuggerpart.moc"