/* * Copyright Johannes Sixt * This file is licensed under the GNU General Public License Version 2. * See the file COPYING in the toplevel directory of the source directory. */ #ifndef DEBUGGER_H #define DEBUGGER_H #include #include #include #include "envvar.h" #include "exprwnd.h" /* some compilers require this */ #ifdef HAVE_CONFIG_H #include "config.h" #endif class ExprWnd; class VarTree; struct ExprValue; class ProgramTypeTable; class KTreeViewItem; class TDEConfig; class TDEConfigBase; class ProgramConfig; class TQListBox; class RegisterInfo; class ThreadInfo; class DebuggerDriver; class CmdQueueItem; class Breakpoint; struct DisassembledCode; struct MemoryDump; struct DbgAddr; class TDEProcess; class KDebugger : public TQObject { Q_OBJECT public: KDebugger(TQWidget* parent, /* will be used as the parent for dialogs */ ExprWnd* localVars, ExprWnd* watchVars, TQListBox* backtrace); ~KDebugger(); /** * This function starts to debug the specified executable using the * specified driver. If a program is currently being debugged, it is * terminated first. Ownership of driver is taken if and only if * true is returned. * * @return false if an error occurs. */ bool debugProgram(const TQString& executable, DebuggerDriver* driver); /** * Uses the specified core to debug the active program. * @param batch tells whether the core file was given on the * command line. */ void useCoreFile(TQString corefile, bool batch); /** * Overrides the program argument in the per-program config * with a new value. */ void overrideProgramArguments(const TQString& args); /** * Uses the specified pid to attach to the active program. */ void setAttachPid(const TQString& pid); /** * Attaches to the specified process and debugs it. */ void attachProgram(const TQString& pid); /** * Returns the file name of the per-program config file for the * specified program. */ static TQString getConfigForExe(const TQString& exe); /** * The driver name entry in the per-program config file. */ static const char DriverNameEntry[]; public slots: /** * Runs the program or continues it if it is stopped at a breakpoint. */ void programRun(); /** * Restarts the debuggee. */ void programRunAgain(); /** * Performs a single-step, possibly stepping into a function call. * If byInsn is true, a step by instruction is performed. */ void programStep(); /** * Performs a single-step, stepping over a function call. * If byInsn is true, a step by instruction is performed. */ void programNext(); /** * Performs a single-step by instruction, possibly stepping into a * function call. */ void programStepi(); /** * Performs a single-step by instruction, stepping over a function * call. */ void programNexti(); /** * Runs the program until it returns from the current function. */ void programFinish(); /** * Kills the program (removes it from memory). */ void programKill(); /** * Interrupts the program if it is currently running. */ void programBreak(); /** * Moves the program counter to the specified line. * If an address is given, it is moved to the address. */ void setProgramCounter(const TQString&, int, const DbgAddr&); public: /** * Queries the user for program arguments. */ void programArgs(TQWidget* parent); /** * Queries the user for program settings: Debugger command, terminal * emulator. */ void programSettings(TQWidget* parent); /** * Setup remote debugging device */ void setRemoteDevice(const TQString& remoteDevice) { m_remoteDevice = remoteDevice; } /** * Run the debuggee until the specified line in the specified file is * reached. * * @return false if the command was not executed, e.g. because the * debuggee is running at the moment. */ bool runUntil(const TQString& fileName, int lineNo); /** * Set a breakpoint. * * @param fileName The source file in which to set the breakpoint. * @param lineNo The zero-based line number. * @param address The exact address of the breakpoint. * @param temporary Specifies whether this is a temporary breakpoint * @return false if the command was not executed, e.g. because the * debuggee is running at the moment. */ bool setBreakpoint(TQString fileName, int lineNo, const DbgAddr& address, bool temporary); /** * Set a breakpoint. * * @param bp Describes the breakpoint. * @param queueOnly If false, the breakpoint is set using a high-priority command. */ void setBreakpoint(Breakpoint* bp, bool queueOnly); /** * Enable or disable a breakpoint at the specified location. * * @param fileName The source file in which the breakpoint is. * @param lineNo The zero-based line number. * @param address The exact address of the breakpoint. * @return false if the command was not executed, e.g. because the * debuggee is running at the moment. */ bool enableDisableBreakpoint(TQString fileName, int lineNo, const DbgAddr& address); /** * Enables or disables the specified breakpoint. * * @return false if the command was not executed, e.g. because the * debuggee is running at the moment. */ bool enableDisableBreakpoint(int id) { return enableDisableBreakpoint(breakpointById(id)); } /** * Removes the specified breakpoint. Note that if bp is an orphaned * breakpoint, then bp is an invalid pointer if (and only if) this * function returns true. * * @return false if the command was not executed, e.g. because the * debuggee is running at the moment. */ bool deleteBreakpoint(int id) { return deleteBreakpoint(breakpointById(id)); } /** * Changes the specified breakpoint's condition and ignore count. * * @return false if the command was not executed, e.g. because the * debuggee is running at the moment. */ bool conditionalBreakpoint(int id, const TQString& condition, int ignoreCount) { return conditionalBreakpoint(breakpointById(id), condition, ignoreCount); } /** * Tells whether one of the single stepping commands can be invoked * (step, next, finish, until, also run). */ bool canSingleStep(); /** * Tells whether a breakpoints can be set, deleted, enabled, or disabled. */ bool canChangeBreakpoints(); /** * Tells whether a the program is loaded, but not active. */ bool canStart(); /** * Add a watch expression. */ void addWatch(const TQString& expr); /** * Retrieves the current status message. */ const TQString& statusMessage() const { return m_statusMessage; } /** * Is the debugger ready to receive another high-priority command? */ bool isReady() const; /** * Is the debuggee running (not just active)? */ bool isProgramRunning() { return m_haveExecutable && m_programRunning; } /** * Do we have an executable set? */ bool haveExecutable() { return m_haveExecutable; } /** * Is the debuggee active, i.e. was it started by the debugger? */ bool isProgramActive() { return m_programActive; } /** * Is the debugger driver idle? */ bool isIdle() const; /* The list of breakpoints. */ typedef std::list::const_iterator BrkptROIterator; BrkptROIterator breakpointsBegin() const { return m_brkpts.begin(); } BrkptROIterator breakpointsEnd() const { return m_brkpts.end(); } const TQString& executable() const { return m_executable; } /** * Terminal emulation level. */ enum TTYLevel { ttyNone = 0, /* ignore output, input triggers EOF */ ttySimpleOutputOnly = 1, /* minmal output emulation, input triggers EOF */ ttyFull = 7 /* program needs full emulation */ }; /** * Returns the level of terminal emulation requested by the inferior. */ TTYLevel ttyLevel() const { return m_ttyLevel; } /** Sets the terminal that is to be used by the debugger. */ void setTerminal(const TQString& term) { m_inferiorTerminal = term; } /** Returns the debugger driver. */ DebuggerDriver* driver() { return m_d; } /** Returns the pid that the debugger is currently attached to. */ const TQString& attachedPid() const { return m_attachedPid; } /** * The memory at that the expression evaluates to is watched. Can be * empty. Triggers a redisplay even if the expression did not change. */ void setMemoryExpression(const TQString& memexpr); /** * Sets how the watched memory location is displayed. * Call setMemoryExpression() to force a redisplay. */ void setMemoryFormat(unsigned format) { m_memoryFormat = format; } // settings void saveSettings(TDEConfig*); void restoreSettings(TDEConfig*); protected: TQString m_inferiorTerminal; TQString m_debuggerCmd; /* per-program setting */ TTYLevel m_ttyLevel; /* level of terminal emulation */ bool startDriver(); void stopDriver(); void writeCommand(); TQStringList m_watchEvalExpr; /* exprs to evaluate for watch window */ std::list m_brkpts; TQString m_memoryExpression; /* memory location to watch */ unsigned m_memoryFormat; /* how that output should look */ protected slots: void parse(CmdQueueItem* cmd, const char* output); protected: void handleRunCommands(const char* output); void updateAllExprs(); void updateProgEnvironment(const TQString& args, const TQString& wd, const TQDict& newVars, const TQStringList& newOptions); void parseLocals(const char* output, std::list& newVars); void handleLocals(const char* output); bool handlePrint(CmdQueueItem* cmd, const char* output); bool handlePrintDeref(CmdQueueItem* cmd, const char* output); void handleBacktrace(const char* output); void handleFrameChange(const char* output); void handleFindType(CmdQueueItem* cmd, const char* output); void handlePrintStruct(CmdQueueItem* cmd, const char* output); void handleSharedLibs(const char* output); void handleRegisters(const char* output); void handleMemoryDump(const char* output); void handleInfoLine(CmdQueueItem* cmd, const char* output); void handleDisassemble(CmdQueueItem* cmd, const char* output); void handleThreadList(const char* output); void handleSetPC(const char* output); void handleSetVariable(CmdQueueItem* cmd, const char* output); void evalExpressions(); void evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate); void evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate); void dereferencePointer(ExprWnd* wnd, VarTree* var, bool immediate); void determineType(ExprWnd* wnd, VarTree* var); void queueMemoryDump(bool immediate); CmdQueueItem* loadCoreFile(); void openProgramConfig(const TQString& name); typedef std::list::iterator BrkptIterator; BrkptIterator breakpointByFilePos(TQString file, int lineNo, const DbgAddr& address); BrkptIterator breakpointById(int id); CmdQueueItem* executeBreakpoint(const Breakpoint* bp, bool queueOnly); void newBreakpoint(CmdQueueItem* cmd, const char* output); void updateBreakList(const char* output); bool stopMayChangeBreakList() const; void saveBreakpoints(ProgramConfig* config); void restoreBreakpoints(ProgramConfig* config); bool enableDisableBreakpoint(BrkptIterator bp); bool deleteBreakpoint(BrkptIterator bp); bool conditionalBreakpoint(BrkptIterator bp, const TQString& condition, int ignoreCount); bool m_haveExecutable; /* has an executable been specified */ bool m_programActive; /* is the program active (possibly halting in a brkpt)? */ bool m_programRunning; /* is the program executing (not stopped)? */ bool m_sharedLibsListed; /* do we know the shared libraries loaded by the prog? */ TQString m_executable; TQString m_corefile; TQString m_attachedPid; /* user input of attaching to pid */ TQString m_programArgs; TQString m_remoteDevice; TQString m_programWD; /* working directory of gdb */ TQDict m_envVars; /* environment variables set by user */ TQStringList m_boolOptions; /* boolean options */ TQStringList m_sharedLibs; /* shared libraries used by program */ ProgramTypeTable* m_typeTable; /* known types used by the program */ ProgramConfig* m_programConfig; /* program-specific settings (brkpts etc) */ void saveProgramSettings(); void restoreProgramSettings(); TQString readDebuggerCmd(); // debugger process DebuggerDriver* m_d; bool m_explicitKill; /* whether we are killing gdb ourselves */ TQString m_statusMessage; protected slots: void gdbExited(TDEProcess*); void slotInferiorRunning(); void backgroundUpdate(); void gotoFrame(int); void slotExpanding(TQListViewItem*); void slotDeleteWatch(); void slotValuePopup(const TQString&); void slotDisassemble(const TQString&, int); void slotValueEdited(VarTree*, const TQString&); public slots: void setThread(int); void shutdown(); signals: /** * This signal is emitted before the debugger is started. The slot is * supposed to set up m_inferiorTerminal. */ void debuggerStarting(); /** * This signal is emitted whenever a part of the debugger needs to * highlight the specfied source code line (e.g. when the program * stops). * * @param file specifies the file; this is not necessarily a full path * name, and if it is relative, you won't know relative to what, you * can only guess. * @param lineNo specifies the line number (0-based!) (this may be * negative, in which case the file should be activated, but the line * should NOT be changed). * @param address specifies the exact address of the PC or is empty. */ void activateFileLine(const TQString& file, int lineNo, const DbgAddr& address); /** * This signal indicates that the program counter has changed. * * @param filename specifies the filename where the program stopped * @param lineNo specifies the line number (zero-based); it can be -1 * if it is unknown * @param address specifies the address that the instruction pointer * points to. * @param frameNo specifies the frame number: 0 is the innermost frame, * positive numbers are frames somewhere up the stack (indicates points * where a function was called); the latter cases should be indicated * differently in the source window. */ void updatePC(const TQString& filename, int lineNo, const DbgAddr& address, int frameNo); /** * This signal is emitted when gdb detects that the executable has been * updated, e.g. recompiled. (You usually need not handle this signal * if you are the editor which changed the executable.) */ void executableUpdated(); /** * Indicates that a new status message is available. */ void updateStatusMessage(); /** * Indicates that the internal state of the debugger has changed, and * that this will very likely have an impact on the UI. */ void updateUI(); /** * Indicates that the list of breakpoints has possibly changed. */ void breakpointsChanged(); /** * Indicates that the register values have possibly changed. */ void registersChanged(const std::list&); /** * Indicates that the list of threads has possibly changed. */ void threadsChanged(const std::list&); /** * Indicates that the value for a value popup is ready. */ void valuePopup(const TQString&); /** * Provides the disassembled code of the location given by file and * line number (zero-based). */ void disassembled(const TQString& file, int line, const std::list& code); /** * Indicates that the program has stopped for any reason: by a * breakpoint, by a signal that the debugger driver caught, by a single * step instruction. */ void programStopped(); /** * Indicates that a new memory dump output is ready. * @param msg is an error message or empty * @param memdump is the memory dump */ void memoryDumpChanged(const TQString&, const std::list&); /** * Gives other objects a chance to save program specific settings. */ void saveProgramSpecific(TDEConfigBase* config); /** * Gives other objects a chance to restore program specific settings. */ void restoreProgramSpecific(TDEConfigBase* config); protected: ExprWnd& m_localVariables; ExprWnd& m_watchVariables; TQListBox& m_btWindow; // implementation helpers protected: TQWidget* parentWidget() { return static_cast(parent()); } }; #endif // DEBUGGER_H