You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
557 lines
17 KiB
557 lines
17 KiB
/*
|
|
* 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 <tqtimer.h>
|
|
#include <tqdict.h>
|
|
#include <tqstringlist.h>
|
|
#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
|
|
{
|
|
TQ_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<Breakpoint>::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<Breakpoint> 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<EnvVar>& newVars,
|
|
const TQStringList& newOptions);
|
|
void parseLocals(const char* output, std::list<ExprValue*>& 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<Breakpoint>::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<EnvVar> 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<RegisterInfo>&);
|
|
|
|
/**
|
|
* Indicates that the list of threads has possibly changed.
|
|
*/
|
|
void threadsChanged(const std::list<ThreadInfo>&);
|
|
|
|
/**
|
|
* 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<DisassembledCode>& 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<MemoryDump>&);
|
|
|
|
/**
|
|
* 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<TQWidget*>(parent()); }
|
|
};
|
|
|
|
#endif // DEBUGGER_H
|