haiku/headers/private/debugger/controllers/TeamDebugger.h

301 lines
9.1 KiB
C
Raw Normal View History

/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2013-2016, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#ifndef TEAM_DEBUGGER_H
#define TEAM_DEBUGGER_H
#include <debugger.h>
#include <Looper.h>
#include "Team.h"
#include "TeamSettings.h"
#include "ThreadHandler.h"
#include "UserInterface.h"
#include "util/Worker.h"
class DebugEvent;
class DebuggerInterface;
class DebugReportGenerator;
class FileManager;
class ImageCreatedEvent;
class ImageDebugInfoLoadingState;
class ImageDeletedEvent;
class PostSyscallEvent;
class SettingsManager;
class TeamDebugInfo;
class TeamDeletedEvent;
class TeamExecEvent;
class TeamMemoryBlockManager;
class Thread;
class ThreadCreatedEvent;
class ThreadDeletedEvent;
class ThreadRenamedEvent;
class ThreadPriorityChangedEvent;
class WatchpointManager;
class TeamDebugger : public BLooper, private UserInterfaceListener,
private JobListener, private Team::Listener {
public:
class Listener;
public:
TeamDebugger(Listener* listener,
UserInterface* userInterface,
SettingsManager* settingsManager);
~TeamDebugger();
status_t Init(DebuggerInterface* interface,
thread_id threadID, int argc,
const char* const* argv,
bool stopInMain);
void Activate();
team_id TeamID() const { return fTeamID; }
bool IsPostMortem() const { return fIsPostMortem; }
int ArgumentCount() const
{ return fCommandLineArgc; }
const char** Arguments() const
{ return fCommandLineArgv; }
Debugger: Rework to fully use TargetHostInterface. Application objects: - Rework and simplify to take into account that they will no longer be directly managing the team debugger list. Requests to start a new debugger are still funnelled through here however, and as such, said requests must now provide the appropriate target host to start with. Adjust StartTeamWindow and TeamsWindow accordingly. - On global init, always create an instance of the local interface. TargetHostInterface: - Convert to BLooper and implement TeamDebugger's Listener interface. TargetHostInterfaces now directly manage their TeamDebugger instances, and consequently take over the equivalent duties that the main application previously had. - Adjust signatures of Attach/CreateTeam to add const. Adjust LocalTargetHostInterface accordingly. - Add accessor to determine if a given interface is local or not. Will be needed for the TeamDebugger's file manager eventually so it knows if it needs to request remote files if no matching local file is found. - Add accessor to start a TeamDebugger instance, and corresponding options structure. TargetHostInterfaceRoster: - Minor adjustments to host interface initialization to take into account needing to start the looper. - Add accessor for number of running team debuggers, for the main app to use when deciding to quit. TeamDebugger: - Add accessor for SettingsManager. Needed for the case of a restart request, as the host interfaces do not have direct access to it. TeamsWindow: - For now, always grab the local host interface when initializing the window. Once the remote interface is implemented, this will need to be adjusted, but the appropriate UI for creating/selecting it is needed first anyways. With these changes, the main application is fully host-agnostic, and all management of actual debuggers is delegated to their parent host interfaces. There still needs to be a listener interface for the host interface and/or roster though, so that the application can be made aware of when debuggers quit, as this drives whether it's time to terminate the app or not.
2016-04-21 02:23:01 +03:00
SettingsManager* GetSettingsManager() const
{ return fSettingsManager; }
UserInterface* GetUserInterface() const
{ return fUserInterface; }
virtual void MessageReceived(BMessage* message);
private:
// UserInterfaceListener
* Worker: - Made Job Referenceable. - Turned JobKey into an abstract base class to add flexibility. The new SimpleJobKey is a subclass with the former functionality. * TeamWindow: Removed the TeamWindow* parameter from the listener hooks. The TeamDebugger knows anyway. * Added IDs to Variable, Function, and FunctionInstance. The latter two generate the ID on the fly, Variable stores it. * SpecificImageDebugInfo::CreateFrame(): Changed FunctionDebugInfo* debug parameter to FunctionInstance* to provide more info (the function ID). * DwarfInterfaceFactory/DwarfImageDebugInfo: - Added class DwarfFunctionParameterID, an ID class implementation for function parameters and set the IDs on the parameter objects. - Retrieve the size of a type (i.e. the size of its objects) and store it in DwarfType. - If a parameter's ValueLocation doesn't have a size, set that of the respective type. - Map the register indicies in the parameters' ValueLocations from DWARF to our indices. * Added class TypeComponentPath for identifying subcomponents in types. * Added class StackFrameValues, a container associating variables and their subcomponents with values. * StackFrame does now have a StackFrameValues object for parameters and local variables and a mechanism to notify listeners when values have been retrieved. * Added GetStackFrameValueJob to retrieve variable values. Lots of functionality is missing yet. Most notably it doesn't retrieves values for subcomponents. * Wired everything to trigger loading of variable values and getting notified when done. * VariablesView: Added a value column. This is all very basic and has to be done differently, but at least values for the parameters can be seen already. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31636 a95241bf-73f2-0310-859d-f6bbb57e9c96
2009-07-19 03:52:16 +04:00
virtual void FunctionSourceCodeRequested(
FunctionInstance* function,
bool forceDisassembly = false);
virtual void SourceEntryLocateRequested(
const char* sourcePath,
const char* locatedPath);
virtual void SourceEntryInvalidateRequested(
LocatableFile* sourceFile);
* Worker: - Made Job Referenceable. - Turned JobKey into an abstract base class to add flexibility. The new SimpleJobKey is a subclass with the former functionality. * TeamWindow: Removed the TeamWindow* parameter from the listener hooks. The TeamDebugger knows anyway. * Added IDs to Variable, Function, and FunctionInstance. The latter two generate the ID on the fly, Variable stores it. * SpecificImageDebugInfo::CreateFrame(): Changed FunctionDebugInfo* debug parameter to FunctionInstance* to provide more info (the function ID). * DwarfInterfaceFactory/DwarfImageDebugInfo: - Added class DwarfFunctionParameterID, an ID class implementation for function parameters and set the IDs on the parameter objects. - Retrieve the size of a type (i.e. the size of its objects) and store it in DwarfType. - If a parameter's ValueLocation doesn't have a size, set that of the respective type. - Map the register indicies in the parameters' ValueLocations from DWARF to our indices. * Added class TypeComponentPath for identifying subcomponents in types. * Added class StackFrameValues, a container associating variables and their subcomponents with values. * StackFrame does now have a StackFrameValues object for parameters and local variables and a mechanism to notify listeners when values have been retrieved. * Added GetStackFrameValueJob to retrieve variable values. Lots of functionality is missing yet. Most notably it doesn't retrieves values for subcomponents. * Wired everything to trigger loading of variable values and getting notified when done. * VariablesView: Added a value column. This is all very basic and has to be done differently, but at least values for the parameters can be seen already. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31636 a95241bf-73f2-0310-859d-f6bbb57e9c96
2009-07-19 03:52:16 +04:00
virtual void ImageDebugInfoRequested(Image* image);
* EnumerationValue -> EnumeratorValue * Since some types don't have names (e.g. pointer types or anonymous structs or unions), each type does now also have a unique ID. The global type cache registers types by ID and by name (if they have one). This fixes clashes of types with empty names. * Completely refactored the code dealing with variable values. Formerly we had Variable and TypeComponentPath to navigate to a component, mapped to a BVariant representing the value. Now we have: * Interface Value with various subclasses (BoolValue, IntegerValue, etc.) to represent a value, with the flexibility for more esoteric values. * A tree of ValueNode+ValueNodeChild objects to represent the components of a variable. On top of each ValueNodeChild sits a ValueNode representing the value of the component, potentially having ValueNodeChild children. This should allow casting a component value, simply by replacing its ValueNode. * Interface ValueHandler and various implementations for the different value types. It is basically a factory for classes allowing to format/display a value. * ValueHandlerRoster -- a registry for ValueHandlers, finding the best one for a given value. * Interface TypeHandler and various implementions for the different type kinds (primitive, compound, address, etc.). It is basically a factory for ValueNodes for that type. * TypeHandlerRoster -- a registry for TypeHandlers, finding the best one for a given type. That's still a bit work in progress. It introduces at least one regression: The VariablesView doesn't save/restore its state anymore. Will take a while until that is added back. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33907 a95241bf-73f2-0310-859d-f6bbb57e9c96
2009-11-05 21:15:21 +03:00
virtual void ValueNodeValueRequested(CpuState* cpuState,
ValueNodeContainer* container,
ValueNode* valueNode);
virtual void ValueNodeWriteRequested(ValueNode* node,
CpuState* state,
Value* newValue);
* Worker: - Made Job Referenceable. - Turned JobKey into an abstract base class to add flexibility. The new SimpleJobKey is a subclass with the former functionality. * TeamWindow: Removed the TeamWindow* parameter from the listener hooks. The TeamDebugger knows anyway. * Added IDs to Variable, Function, and FunctionInstance. The latter two generate the ID on the fly, Variable stores it. * SpecificImageDebugInfo::CreateFrame(): Changed FunctionDebugInfo* debug parameter to FunctionInstance* to provide more info (the function ID). * DwarfInterfaceFactory/DwarfImageDebugInfo: - Added class DwarfFunctionParameterID, an ID class implementation for function parameters and set the IDs on the parameter objects. - Retrieve the size of a type (i.e. the size of its objects) and store it in DwarfType. - If a parameter's ValueLocation doesn't have a size, set that of the respective type. - Map the register indicies in the parameters' ValueLocations from DWARF to our indices. * Added class TypeComponentPath for identifying subcomponents in types. * Added class StackFrameValues, a container associating variables and their subcomponents with values. * StackFrame does now have a StackFrameValues object for parameters and local variables and a mechanism to notify listeners when values have been retrieved. * Added GetStackFrameValueJob to retrieve variable values. Lots of functionality is missing yet. Most notably it doesn't retrieves values for subcomponents. * Wired everything to trigger loading of variable values and getting notified when done. * VariablesView: Added a value column. This is all very basic and has to be done differently, but at least values for the parameters can be seen already. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31636 a95241bf-73f2-0310-859d-f6bbb57e9c96
2009-07-19 03:52:16 +04:00
virtual void ThreadActionRequested(thread_id threadID,
uint32 action, target_addr_t address);
virtual void SetBreakpointRequested(target_addr_t address,
bool enabled, bool hidden = false);
virtual void SetBreakpointEnabledRequested(
UserBreakpoint* breakpoint,
bool enabled);
virtual void SetBreakpointConditionRequested(
UserBreakpoint* breakpoint,
const char* condition);
virtual void ClearBreakpointConditionRequested(
UserBreakpoint* breakpoint);
virtual void ClearBreakpointRequested(target_addr_t address);
virtual void ClearBreakpointRequested(
UserBreakpoint* breakpoint);
virtual void SetStopOnImageLoadRequested(bool enabled,
bool useImageNames);
virtual void AddStopImageNameRequested(
const char* name);
virtual void RemoveStopImageNameRequested(
const char* name);
virtual void SetDefaultSignalDispositionRequested(
int32 disposition);
virtual void SetCustomSignalDispositionRequested(
int32 signal, int32 disposition);
virtual void RemoveCustomSignalDispositionRequested(
int32 signal);
virtual void SetWatchpointRequested(target_addr_t address,
uint32 type, int32 length, bool enabled);
virtual void SetWatchpointEnabledRequested(
Watchpoint *watchpoint, bool enabled);
virtual void ClearWatchpointRequested(target_addr_t address);
virtual void ClearWatchpointRequested(
Watchpoint* breakpoint);
virtual void InspectRequested(target_addr_t address,
TeamMemoryBlock::Listener* listener);
virtual void MemoryWriteRequested(target_addr_t address,
const void* data, target_size_t size);
virtual void ExpressionEvaluationRequested(
SourceLanguage* language,
ExpressionInfo* info,
StackFrame* frame = NULL,
::Thread* thread = NULL);
virtual void DebugReportRequested(entry_ref* targetPath);
virtual void WriteCoreFileRequested(entry_ref* targetPath);
virtual void TeamRestartRequested();
virtual bool UserInterfaceQuitRequested(
QuitOption quitOption);
// JobListener
virtual void JobStarted(Job* job);
virtual void JobDone(Job* job);
virtual void JobWaitingForInput(Job* job);
virtual void JobFailed(Job* job);
virtual void JobAborted(Job* job);
// Team::Listener
virtual void ThreadStateChanged(
const ::Team::ThreadEvent& event);
virtual void ThreadCpuStateChanged(
const ::Team::ThreadEvent& event);
virtual void ThreadStackTraceChanged(
const ::Team::ThreadEvent& event);
virtual void ImageDebugInfoChanged(
const ::Team::ImageEvent& event);
private:
struct ImageHandler;
struct ImageHandlerHashDefinition;
struct ImageInfoPendingThread;
struct ImageInfoPendingThreadHashDefinition;
typedef BOpenHashTable<ImageHandlerHashDefinition> ImageHandlerTable;
typedef BOpenHashTable<ImageInfoPendingThreadHashDefinition>
ImageInfoPendingThreadTable;
private:
static status_t _DebugEventListenerEntry(void* data);
status_t _DebugEventListener();
void _HandleDebuggerMessage(DebugEvent* event);
bool _HandleTeamDeleted(
TeamDeletedEvent* event);
bool _HandleThreadCreated(
ThreadCreatedEvent* event);
bool _HandleThreadRenamed(
ThreadRenamedEvent* event);
bool _HandleThreadPriorityChanged(
ThreadPriorityChangedEvent* event);
bool _HandleThreadDeleted(
ThreadDeletedEvent* event);
bool _HandleImageCreated(
ImageCreatedEvent* event);
bool _HandleImageDeleted(
ImageDeletedEvent* event);
bool _HandlePostSyscall(
PostSyscallEvent* event);
void _PrepareForTeamExec(TeamExecEvent* event);
void _HandleImageDebugInfoChanged(image_id imageID);
void _HandleImageFileChanged(image_id imageID);
void _HandleSetUserBreakpoint(target_addr_t address,
bool enabled, bool hidden);
void _HandleSetUserBreakpoint(
UserBreakpoint* breakpoint, bool enabled);
void _HandleClearUserBreakpoint(
target_addr_t address);
void _HandleClearUserBreakpoint(
UserBreakpoint* breakpoint);
void _HandleSetWatchpoint(target_addr_t address,
uint32 type, int32 length, bool enabled);
void _HandleSetWatchpoint(
Watchpoint* watchpoint, bool enabled);
void _HandleClearWatchpoint( target_addr_t address);
void _HandleClearWatchpoint(Watchpoint* watchpoint);
void _HandleInspectAddress(
target_addr_t address,
TeamMemoryBlock::Listener* listener);
void _HandleWriteMemory(
target_addr_t address, void* data,
target_size_t size);
void _HandleEvaluateExpression(
SourceLanguage* language,
ExpressionInfo* info,
StackFrame* frame,
::Thread* thread);
void _HandleWriteCoreFile(const entry_ref& ref);
status_t _HandleSetArguments(int argc,
const char* const* argv);
void _HandleDebugInfoJobUserInput(
ImageDebugInfoLoadingState* state);
ThreadHandler* _GetThreadHandler(thread_id threadID);
status_t _AddImage(const ImageInfo& imageInfo,
Image** _image = NULL);
void _LoadSettings();
void _SaveSettings();
void _NotifyUser(const char* title,
const char* text,...);
void _ResetUserBackgroundStatusIfNeeded();
// updates user interface to
// ready/completed message
// for background work status
private:
Listener* fListener;
SettingsManager* fSettingsManager;
::Team* fTeam;
team_id fTeamID;
bool fIsPostMortem;
ThreadHandlerTable fThreadHandlers;
// protected by the team lock
ImageHandlerTable* fImageHandlers;
ImageInfoPendingThreadTable* fImageInfoPendingThreads;
DebuggerInterface* fDebuggerInterface;
TeamDebugInfo* fTeamDebugInfo;
FileManager* fFileManager;
Worker* fWorker;
BreakpointManager* fBreakpointManager;
WatchpointManager* fWatchpointManager;
TeamMemoryBlockManager*
fMemoryBlockManager;
DebugReportGenerator*
fReportGenerator;
thread_id fDebugEventListener;
UserInterface* fUserInterface;
volatile bool fTerminating;
bool fKillTeamOnQuit;
TeamSettings fTeamSettings;
int fCommandLineArgc;
const char** fCommandLineArgv;
bool fExecPending;
};
class TeamDebugger::Listener {
public:
virtual ~Listener();
virtual void TeamDebuggerStarted(TeamDebugger* debugger) = 0;
virtual void TeamDebuggerRestartRequested(
TeamDebugger* debugger) = 0;
virtual void TeamDebuggerQuit(TeamDebugger* debugger) = 0;
};
#endif // TEAM_DEBUGGER_H