summaryrefslogtreecommitdiffstats
path: root/languages/cpp/debugger/gdbcontroller.h
diff options
context:
space:
mode:
Diffstat (limited to 'languages/cpp/debugger/gdbcontroller.h')
-rw-r--r--languages/cpp/debugger/gdbcontroller.h358
1 files changed, 358 insertions, 0 deletions
diff --git a/languages/cpp/debugger/gdbcontroller.h b/languages/cpp/debugger/gdbcontroller.h
new file mode 100644
index 00000000..6a9e3385
--- /dev/null
+++ b/languages/cpp/debugger/gdbcontroller.h
@@ -0,0 +1,358 @@
+/***************************************************************************
+ gdbcontroller.h - description
+ -------------------
+ begin : Sun Aug 8 1999
+ copyright : (C) 1999 by John Birch
+ email : jbb@kdevelop.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _GDBCONTROLLER_H_
+#define _GDBCONTROLLER_H_
+
+#include "dbgcontroller.h"
+#include "mi/gdbmi.h"
+#include "mi/miparser.h"
+
+#include <qcstring.h>
+#include <qdom.h>
+#include <qobject.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qmap.h>
+#include <qdatetime.h>
+
+#include <memory>
+#include <set>
+
+class KProcess;
+
+namespace GDBDebugger
+{
+
+class Breakpoint;
+class DbgCommand;
+class GDBCommand;
+class VarItem;
+class STTY;
+
+/**
+ * A front end implementation to the gdb command line debugger
+ * @author jbb
+ */
+
+class GDBController : public DbgController
+{
+ Q_OBJECT
+
+public:
+ GDBController(QDomDocument &projectDom);
+ ~GDBController();
+
+ enum event_t { program_state_changed = 1, program_exited, debugger_exited,
+ thread_or_frame_changed, debugger_busy, debugger_ready,
+ shared_library_loaded,
+ // Raised when debugger believe that program start running.
+ // Can be used to hide current line indicator.
+ // Don't count on this being raise in all cases where
+ // program is running.
+ program_running,
+ connected_to_program
+ };
+
+
+ /** Adds a command to the end of queue of commands to be executed
+ by gdb. The command will be actually sent to gdb only when
+ replies from all previous commands are received and full processed.
+
+ The literal command sent to gdb is obtained by calling
+ cmd->cmdToSend. The call is made immediately before sending the
+ command, so it's possible to use results of prior commands when
+ computing the exact command to send.
+ */
+ void addCommand(GDBCommand* cmd);
+
+ /** Same as above, but internally constructs new GDBCommand
+ instance from the string. */
+ void addCommand(const QString& cmd);
+
+ /** Adds command to the front of the commands queue. It will be executed
+ next.
+
+ This is usefull to implement 'atomic' command sequences. For example,
+ if one wants to switch to each thread in turn, asking gdb where that
+ thread stand, this should never be interrupted by other command, since
+ other commands might not expect that thread magically changes.
+
+ In this specific case, first -thread-list-ids commands is issued. The
+ handler for reply will add a number of command to front, and it will
+ guarantee that no other command will get in between.
+
+ Note that if you call:
+
+ addCommandToFront(cmd1);
+ addCommandToFront(cmd2);
+
+ The execution order will be 'cmd2', then 'cmd1'.
+
+ FIXME: is not used for now, maybe remove.
+ */
+ void addCommandToFront(GDBCommand* cmd);
+
+ /* If current command queue has any command
+ for which isRun is true, inserts 'cmd'
+ before the first such command. Otherwise,
+ works the same as addCommand. */
+ void addCommandBeforeRun(GDBCommand* cmd);
+
+ /** Selects the specified thread/frame. Immediately emits
+ thread_or_frame_changed event.
+ */
+ void selectFrame(int frameNo, int threadNo);
+
+
+ /** Returns the numerical identfier of the current thread,
+ or -1 if the program is not threaded (i.e. there's just
+ one thread.
+ */
+ int currentThread() const;
+
+ int currentFrame() const;
+
+ bool start(const QString& shell,
+ const DomUtil::PairList& run_envvars,
+ const QString& run_directory,
+ const QString &application,
+ const QString& run_arguments);
+
+ int qtVersion() const;
+
+ /**
+ * Call this when something very interesting happens that the user
+ * might be unaware of. It will make KDevelop's taskbar entry flash
+ * if the application doesn't already have focus.
+ * Typical use case: The debugger has stopped on a breakpoint.
+ */
+ void demandAttention() const;
+
+ void pauseApp();
+
+ bool miPendingBreakpoints() const;
+
+protected:
+ enum queue_where { queue_at_end, queue_at_front, queue_before_run };
+
+ void queueCmd(GDBCommand *cmd, enum queue_where queue_where = queue_at_end);
+
+private:
+ void parseLocals (char type, char *buf);
+ /** Parses the CLI output line, and catches interesting messages
+ like "Program exited". This is intended to allow using console
+ commands in the gdb window despite the fact that GDB does not
+ produce right MI notification for CLI commands. I.e. if you
+ run "continue" there will be no MI message if the application has
+ exited.
+ */
+ void parseCliLine (const QString&);
+
+ /** Handles a result response from a MI command -- that is
+ all MI responses except for Stream and Prompt responses.
+ Uses currentCmd to decide what to do with response and
+ calls appropriate method.
+ */
+ void processMICommandResponse(const GDBMI::ResultRecord& r);
+
+ void handleMiFileListExecSourceFile(const GDBMI::ResultRecord& r);
+
+ /** Handles reply from -stack-info-frame command issues
+ after switching the stack frame.
+ */
+ void handleMiFrameSwitch(const GDBMI::ResultRecord& r);
+
+ void executeCmd ();
+ void destroyCmds();
+ void removeInfoRequests();
+ void actOnProgramPauseMI(const GDBMI::ResultRecord& mi_record);
+ /** Called when there are no pending commands and 'state_reload_needed'
+ is true.
+ Issues commands to completely reload all program state shown
+ to the user.
+ */
+ void reloadProgramState();
+
+ void programNoApp(const QString &msg, bool msgBox);
+
+ void setStateOn(int stateOn);
+ void setStateOff(int stateOff);
+ void setState(int newState);
+
+ void debugStateChange(int oldState, int newState);
+ void commandDone();
+ void destroyCurrentCommand();
+
+ /** Removes all 'stateReloading' commands from the queue.
+ */
+ void removeStateReloadingCommands();
+
+ /** Raises the specified event. Should be used instead of
+ emitting 'event' directly, since this method can perform
+ additional book-keeping for events.
+ */
+ void raiseEvent(event_t e);
+
+ void maybeAnnounceWatchpointHit();
+
+ void handleListFeatures(const GDBMI::ResultRecord& result);
+ void startDone();
+
+ /** Default handler for errors.
+ Tries to guess is the error message is telling that target is
+ gone, if so, informs the user.
+ Otherwise, shows a dialog box and reloads view state. */
+ void defaultErrorHandler(const GDBMI::ResultRecord& result);
+
+public:
+ bool stateIsOn(int state);
+
+public slots:
+ void configure();
+
+
+ //void slotStart(const QString& shell, const QString &application);
+ void slotCoreFile(const QString &coreFile);
+ void slotAttachTo(int pid);
+
+ void slotStopDebugger();
+
+ void slotRun();
+ void slotKill();
+ void slotRunUntil(const QString &filename, int lineNum);
+ void slotJumpTo(const QString &filename, int lineNum);
+ void slotStepInto();
+ void slotStepOver();
+ void slotStepIntoIns();
+ void slotStepOverIns();
+ void slotStepOutOff();
+
+ void slotBreakInto();
+
+ void slotUserGDBCmd(const QString&);
+
+ // Pops up a dialog box with some hopefully
+ // detailed information about which state debugger
+ // is in, which commands were sent and so on.
+ void explainDebuggerStatus();
+
+
+protected slots:
+ void slotDbgStdout(KProcess *proc, char *buf, int buflen);
+ void slotDbgStderr(KProcess *proc, char *buf, int buflen);
+ void slotDbgWroteStdin(KProcess *proc);
+ void slotDbgProcessExited(KProcess *proc);
+
+signals:
+
+ /** This signal is emitted whenever the given event in a program
+ happens. See DESIGN.txt for expected handled of each event.
+
+ NOTE: this signal should never be emitted directly. Instead,
+ use raiseEvent.
+ */
+ void event(GDBController::event_t e);
+
+ void debuggerAbnormalExit();
+
+
+ /** Emitted immediately after breakpoint is hit, before any commands
+ are sent and before current line indicator is shown. */
+ void breakpointHit(int id);
+ /** Emitted for watchpoint hit, after line indicator is shown. */
+ void watchpointHit(int id,
+ const QString& oldValue, const QString& newValue);
+
+private:
+ int currentFrame_;
+ int viewedThread_;
+
+ // The output from gdb that was not parsed yet
+ QCString gdbOutput_;
+ // The output from gdb that arrived where we was
+ // parsing the previous output. To avoid messing
+ // things up, it's not directly added to
+ // gdbOutput_ but stored for future use.
+ // VP: It's not clear why the previous code was doing
+ // this, and holdingZone_ won't be processed until
+ // next output arrives, so probably should be just removed.
+ QCString holdingZone_;
+
+ QPtrList<GDBCommand> cmdList_;
+ GDBCommand* currentCmd_;
+
+ STTY* tty_;
+ QString badCore_;
+ QString application_;
+
+ // Gdb command that should be issued when we stop on breakpoint
+ // with the given gdb breakpoint id.
+ QMap<int, const Breakpoint*> tracedBreakpoints_;
+
+ // Some state variables
+ int state_;
+ bool programHasExited_;
+
+ // Configuration values
+ QDomDocument &dom;
+ bool config_breakOnLoadingLibrary_;
+ bool config_forceBPSet_;
+ bool config_displayStaticMembers_;
+ bool config_asmDemangle_;
+ bool config_dbgTerminal_;
+ QString config_gdbPath_;
+ QString config_dbgShell_;
+ QCString config_configGdbScript_;
+ QCString config_runShellScript_;
+ QCString config_runGdbScript_;
+ int config_outputRadix_;
+
+ MIParser mi_parser_;
+ // As of gdb 6.3, the *stopped packet does not contain
+ // full file name. So we need to send another command to
+ // fetch that, to highlight current line.
+ // After highting current line we need to do something more,
+ // like announcing write watchpoints, and so need to have
+ // access to the stop packet. So store it here.
+ std::auto_ptr<GDBMI::ResultRecord> last_stop_result;
+
+ // Gdb 6.4 (and 6.3) does not support "character" format with MI,
+ // so the only way it can work is via the "print" command. As gdb
+ // outputs things, we'll grep for lines that look like output from
+ // print, and store such lines in this variable, so later use.
+ QCString print_command_result;
+
+ bool state_reload_needed;
+
+ QTime commandExecutionTime;
+
+ bool stateReloadInProgress_;
+
+ /** Commands issues as result of the 'program_state_changed'
+ event. */
+ std::set<GDBCommand*> stateReloadingCommands_;
+
+ bool saw_gdb_prompt_;
+
+ /** Does the used GDB supports pending breakpoints in MI? */
+ bool mi_pending_breakpoints_;
+};
+
+}
+
+#endif