root/headers/private/debugger/model/Team.h
/*
 * 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_H
#define TEAM_H

#include <map>

#include <Locker.h>
#include <StringList.h>

#include <ObjectList.h>

#include "Image.h"
#include "ImageInfo.h"
#include "TargetAddressRange.h"
#include "Thread.h"
#include "ThreadInfo.h"
#include "UserBreakpoint.h"
#include "Watchpoint.h"


// team event types
enum {
        TEAM_EVENT_TEAM_RENAMED,

        TEAM_EVENT_THREAD_ADDED,
        TEAM_EVENT_THREAD_REMOVED,
        TEAM_EVENT_IMAGE_ADDED,
        TEAM_EVENT_IMAGE_REMOVED,

        TEAM_EVENT_THREAD_STATE_CHANGED,
        TEAM_EVENT_THREAD_CPU_STATE_CHANGED,
        TEAM_EVENT_THREAD_STACK_TRACE_CHANGED,

        TEAM_EVENT_IMAGE_DEBUG_INFO_CHANGED,

        TEAM_EVENT_IMAGE_LOAD_SETTINGS_CHANGED,
        TEAM_EVENT_IMAGE_LOAD_NAME_ADDED,
        TEAM_EVENT_IMAGE_LOAD_NAME_REMOVED,

        TEAM_EVENT_DEFAULT_SIGNAL_DISPOSITION_CHANGED,
        TEAM_EVENT_CUSTOM_SIGNAL_DISPOSITION_CHANGED,
        TEAM_EVENT_CUSTOM_SIGNAL_DISPOSITION_REMOVED,

        TEAM_EVENT_CONSOLE_OUTPUT_RECEIVED,

        TEAM_EVENT_BREAKPOINT_ADDED,
        TEAM_EVENT_BREAKPOINT_REMOVED,
        TEAM_EVENT_USER_BREAKPOINT_CHANGED,

        TEAM_EVENT_WATCHPOINT_ADDED,
        TEAM_EVENT_WATCHPOINT_REMOVED,
        TEAM_EVENT_WATCHPOINT_CHANGED,

        TEAM_EVENT_DEBUG_REPORT_CHANGED,

        TEAM_EVENT_CORE_FILE_CHANGED,

        TEAM_EVENT_MEMORY_CHANGED
};


class Architecture;
class Breakpoint;
class BStringList;
class Function;
class FunctionID;
class FunctionInstance;
class LocatableFile;
class SourceCode;
class SourceLocation;
class Statement;
class TeamDebugInfo;
class TeamMemory;
class TeamTypeInformation;
class UserBreakpoint;
class Value;


typedef std::map<int32, int32> SignalDispositionMappings;


class Team {
public:
                        class Event;
                        class BreakpointEvent;
                        class ConsoleOutputEvent;
                        class DebugReportEvent;
                        class MemoryChangedEvent;
                        class ImageEvent;
                        class ImageLoadEvent;
                        class ImageLoadNameEvent;
                        class DefaultSignalDispositionEvent;
                        class CustomSignalDispositionEvent;
                        class ThreadEvent;
                        class UserBreakpointEvent;
                        class WatchpointEvent;
                        class CoreFileChangedEvent;
                        class Listener;

public:
                                                                Team(team_id teamID, TeamMemory* teamMemory,
                                                                        Architecture* architecture,
                                                                        TeamDebugInfo* debugInfo,
                                                                        TeamTypeInformation* typeInformation);
                                                                ~Team();

                        status_t                        Init();

                        bool                            Lock()          { return fLock.Lock(); }
                        void                            Unlock()        { fLock.Unlock(); }

                        team_id                         ID() const                      { return fID; }
                        TeamMemory*                     GetTeamMemory() const
                                                                        { return fTeamMemory; }
                        Architecture*           GetArchitecture() const
                                                                        { return fArchitecture; }
                        TeamDebugInfo*          DebugInfo() const       { return fDebugInfo; }
                        TeamTypeInformation*
                                                                GetTeamTypeInformation() const
                                                                        { return fTypeInformation; }

                        const char*                     Name() const    { return fName.String(); }
                        void                            SetName(const BString& name);

                        void                            AddThread(::Thread* thread);
                        status_t                        AddThread(const ThreadInfo& threadInfo,
                                                                        ::Thread** _thread = NULL);
                        void                            RemoveThread(::Thread* thread);
                        bool                            RemoveThread(thread_id threadID);
                        ::Thread*                       ThreadByID(thread_id threadID) const;
                        const ThreadList&       Threads() const;

                        status_t                        AddImage(const ImageInfo& imageInfo,
                                                                        LocatableFile* imageFile,
                                                                        Image** _image = NULL);
                        void                            RemoveImage(Image* image);
                        bool                            RemoveImage(image_id imageID);
                        Image*                          ImageByID(image_id imageID) const;
                        Image*                          ImageByAddress(target_addr_t address) const;
                        const ImageList&        Images() const;
                        void                            ClearImages();

                        bool                            AddStopImageName(const BString& name);
                        void                            RemoveStopImageName(const BString& name);
                        const BStringList&      StopImageNames() const;

                        void                            SetStopOnImageLoad(bool enabled,
                                                                        bool useImageNameList);
                        bool                            StopOnImageLoad() const
                                                                        { return fStopOnImageLoad; }
                        bool                            StopImageNameListEnabled() const
                                                                        { return fStopImageNameListEnabled; }

                        void                            SetDefaultSignalDisposition(int32 disposition);
                        int32                           DefaultSignalDisposition() const
                                                                        { return fDefaultSignalDisposition; }
                        bool                            SetCustomSignalDisposition(int32 signal,
                                                                        int32 disposition);
                        void                            RemoveCustomSignalDisposition(int32 signal);
                        int32                           SignalDispositionFor(int32 signal) const;
                                                                        // if no custom disposition is found,
                                                                        // returns default
                        const SignalDispositionMappings&
                                                                GetSignalDispositionMappings() const;

                        void                            ClearSignalDispositionMappings();

                        bool                            AddBreakpoint(Breakpoint* breakpoint);
                                                                        // takes over reference (also on error)
                        void                            RemoveBreakpoint(Breakpoint* breakpoint);
                                                                        // releases its own reference
                        int32                           CountBreakpoints() const;
                        Breakpoint*                     BreakpointAt(int32 index) const;
                        Breakpoint*                     BreakpointAtAddress(
                                                                        target_addr_t address) const;
                        void                            GetBreakpointsInAddressRange(
                                                                        TargetAddressRange range,
                                                                        BObjectList<UserBreakpoint>& breakpoints)
                                                                                const;
                        void                            GetBreakpointsForSourceCode(
                                                                        SourceCode* sourceCode,
                                                                        BObjectList<UserBreakpoint>& breakpoints)
                                                                                const;

                        void                            AddUserBreakpoint(
                                                                        UserBreakpoint* userBreakpoint);
                        void                            RemoveUserBreakpoint(
                                                                        UserBreakpoint* userBreakpoint);
                        const UserBreakpointList& UserBreakpoints() const
                                                                        { return fUserBreakpoints; }

                        bool                            AddWatchpoint(Watchpoint* watchpoint);
                                                                        // takes over reference (also on error)
                        void                            RemoveWatchpoint(Watchpoint* watchpoint);
                                                                        // releases its own reference
                        int32                           CountWatchpoints() const;
                        Watchpoint*                     WatchpointAt(int32 index) const;
                        Watchpoint*                     WatchpointAtAddress(
                                                                        target_addr_t address) const;
                        void                            GetWatchpointsInAddressRange(
                                                                        TargetAddressRange range,
                                                                        BObjectList<Watchpoint>& watchpoints)
                                                                                const;
                        const WatchpointList& Watchpoints() const
                                                                        { return fWatchpoints; }

                        status_t                        GetStatementAtAddress(target_addr_t address,
                                                                        FunctionInstance*& _function,
                                                                        Statement*& _statement);
                                                                        // returns a reference to the statement,
                                                                        // not to the functions instance, though,
                                                                        // caller must lock
                        status_t                        GetStatementAtSourceLocation(
                                                                        SourceCode* sourceCode,
                                                                        const SourceLocation& location,
                                                                        Statement*& _statement);
                                                                        // returns a reference to the statement
                                                                        // (any matching statement!),
                                                                        // caller must lock,

                        Function*                       FunctionByID(FunctionID* functionID) const;

                        void                            AddListener(Listener* listener);
                        void                            RemoveListener(Listener* listener);

                        // service methods for Thread
                        void                            NotifyThreadStateChanged(::Thread* thread);
                        void                            NotifyThreadCpuStateChanged(::Thread* thread);
                        void                            NotifyThreadStackTraceChanged(
                                                                        ::Thread* thread);

                        // service methods for Image
                        void                            NotifyImageDebugInfoChanged(Image* image);

                        // service methods for Image load settings
                        void                            NotifyStopOnImageLoadChanged(bool enabled,
                                                                        bool useImageNameList);
                        void                            NotifyStopImageNameAdded(const BString& name);
                        void                            NotifyStopImageNameRemoved(
                                                                        const BString& name);

                        // service methods for Signal Disposition settings
                        void                            NotifyDefaultSignalDispositionChanged(
                                                                        int32 newDisposition);
                        void                            NotifyCustomSignalDispositionChanged(
                                                                        int32 signal, int32 disposition);
                        void                            NotifyCustomSignalDispositionRemoved(
                                                                        int32 signal);

                        // service methods for console output
                        void                            NotifyConsoleOutputReceived(
                                                                        int32 fd, const BString& output);

                        // breakpoint related service methods
                        void                            NotifyUserBreakpointChanged(
                                                                        UserBreakpoint* breakpoint);

                        // watchpoint related service methods
                        void                            NotifyWatchpointChanged(
                                                                        Watchpoint* watchpoint);

                        // debug report related service methods
                        void                            NotifyDebugReportChanged(
                                                                        const char* reportPath, status_t result);

                        // core file related service methods
                        void                            NotifyCoreFileChanged(
                                                                        const char* targetPath);

                        // memory write related service methods
                        void                            NotifyMemoryChanged(target_addr_t address,
                                                                        target_size_t size);

private:
                        struct BreakpointByAddressPredicate;
                        struct WatchpointByAddressPredicate;

                        typedef BObjectList<Breakpoint> BreakpointList;
                        typedef DoublyLinkedList<Listener> ListenerList;

private:
                        void                            _NotifyTeamRenamed();
                        void                            _NotifyThreadAdded(::Thread* thread);
                        void                            _NotifyThreadRemoved(::Thread* thread);
                        void                            _NotifyImageAdded(Image* image);
                        void                            _NotifyImageRemoved(Image* image);

private:
                        BLocker                         fLock;
                        team_id                         fID;
                        TeamMemory*                     fTeamMemory;
                        TeamTypeInformation*
                                                                fTypeInformation;
                        Architecture*           fArchitecture;
                        TeamDebugInfo*          fDebugInfo;
                        BString                         fName;
                        ThreadList                      fThreads;
                        ImageList                       fImages;
                        bool                            fStopOnImageLoad;
                        bool                            fStopImageNameListEnabled;
                        BStringList                     fStopImageNames;
                        int32                           fDefaultSignalDisposition;
                        SignalDispositionMappings
                                                                fCustomSignalDispositions;
                        BreakpointList          fBreakpoints;
                        WatchpointList          fWatchpoints;
                        UserBreakpointList      fUserBreakpoints;
                        ListenerList            fListeners;
};


class Team::Event {
public:
                                                                Event(uint32 type, Team* team);

                        uint32                          EventType() const       { return fEventType; }
                        Team*                           GetTeam() const         { return fTeam; }

protected:
                        uint32                          fEventType;
                        Team*                           fTeam;
};


class Team::ThreadEvent : public Event {
public:
                                                                ThreadEvent(uint32 type, ::Thread* thread);

                        ::Thread*                       GetThread() const       { return fThread; }

protected:
                        ::Thread*                       fThread;
};


class Team::ImageEvent : public Event {
public:
                                                                ImageEvent(uint32 type, Image* image);

                        Image*                          GetImage() const        { return fImage; }

protected:
                        Image*                          fImage;
};


class Team::ImageLoadEvent : public Event {
public:
                                                                ImageLoadEvent(uint32 type, Team* team,
                                                                        bool stopOnImageLoad,
                                                                        bool stopImageNameListEnabled);

                        bool                            StopOnImageLoad() const
                                                                        { return fStopOnImageLoad; }
                        bool                            StopImageNameListEnabled() const
                                                                        { return fStopImageNameListEnabled; }

private:
                        bool                            fStopOnImageLoad;
                        bool                            fStopImageNameListEnabled;
};


class Team::ImageLoadNameEvent : public Event {
public:
                                                                ImageLoadNameEvent(uint32 type, Team* team,
                                                                        const BString& name);

                        const BString&          ImageName() const { return fImageName; }

private:
                        BString                         fImageName;
};


class Team::DefaultSignalDispositionEvent : public Event {
public:
                                                                DefaultSignalDispositionEvent(uint32 type,
                                                                        Team* team, int32 disposition);

                        int32                           DefaultDisposition() const
                                                                        { return fDefaultDisposition; }

private:
                        int32                           fDefaultDisposition;
};


class Team::CustomSignalDispositionEvent : public Event {
public:
                                                                CustomSignalDispositionEvent(uint32 type,
                                                                        Team* team, int32 signal,
                                                                        int32 disposition);

                        int32                           Signal() const { return fSignal; }
                        int32                           Disposition() const { return fDisposition; }

private:
                        int32                           fSignal;
                        int32                           fDisposition;
};


class Team::BreakpointEvent : public Event {
public:
                                                                BreakpointEvent(uint32 type, Team* team,
                                                                        Breakpoint* breakpoint);

                        Breakpoint*                     GetBreakpoint() const   { return fBreakpoint; }

protected:
                        Breakpoint*                     fBreakpoint;
};


class Team::ConsoleOutputEvent : public Event {
public:
                                                                ConsoleOutputEvent(uint32 type, Team* team,
                                                                        int32 fd, const BString& output);

                        int32                           Descriptor() const      { return fDescriptor; }
                        const BString&          Output() const          { return fOutput; }

protected:
                        int32                           fDescriptor;
                        BString                         fOutput;
};


class Team::DebugReportEvent : public Event {
public:
                                                                DebugReportEvent(uint32 type, Team* team,
                                                                        const char* reportPath,
                                                                        status_t finalStatus);

                        const char*                     GetReportPath() const   { return fReportPath; }
                        status_t                        GetFinalStatus() const  { return fFinalStatus; }
protected:
                        const char*                     fReportPath;
                        status_t                        fFinalStatus;
};


class Team::CoreFileChangedEvent : public Event {
public:
                                                                CoreFileChangedEvent(uint32 type, Team* team,
                                                                        const char* targetPath);
                        const char*                     GetTargetPath() const   { return fTargetPath; }
protected:
                        const char*                     fTargetPath;
};


class Team::MemoryChangedEvent : public Event {
public:
                                                                MemoryChangedEvent(uint32 type, Team* team,
                                                                        target_addr_t address, target_size_t size);

                        target_addr_t           GetTargetAddress() const
                                                                        { return fTargetAddress; }

                        target_size_t           GetSize() const { return fSize; }
protected:
                        target_addr_t           fTargetAddress;
                        target_size_t           fSize;
};


class Team::WatchpointEvent : public Event {
public:
                                                                WatchpointEvent(uint32 type, Team* team,
                                                                        Watchpoint* watchpoint);

                        Watchpoint*                     GetWatchpoint() const   { return fWatchpoint; }

protected:
                        Watchpoint*                     fWatchpoint;
};


class Team::UserBreakpointEvent : public Event {
public:
                                                                UserBreakpointEvent(uint32 type, Team* team,
                                                                        UserBreakpoint* breakpoint);

                        UserBreakpoint*         GetBreakpoint() const   { return fBreakpoint; }

protected:
                        UserBreakpoint*         fBreakpoint;
};


class Team::Listener : public DoublyLinkedListLinkImpl<Team::Listener> {
public:
        virtual                                         ~Listener();

        virtual void                            TeamRenamed(
                                                                        const Team::Event& event);

        virtual void                            ThreadAdded(const Team::ThreadEvent& event);
        virtual void                            ThreadRemoved(const Team::ThreadEvent& event);

        virtual void                            ImageAdded(const Team::ImageEvent& event);
        virtual void                            ImageRemoved(const Team::ImageEvent& event);

        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);

        virtual void                            StopOnImageLoadSettingsChanged(
                                                                        const Team::ImageLoadEvent& event);
        virtual void                            StopOnImageLoadNameAdded(
                                                                        const Team::ImageLoadNameEvent& event);
        virtual void                            StopOnImageLoadNameRemoved(
                                                                        const Team::ImageLoadNameEvent& event);

        virtual void                            DefaultSignalDispositionChanged(
                                                                        const Team::DefaultSignalDispositionEvent&
                                                                                event);
        virtual void                            CustomSignalDispositionChanged(
                                                                        const Team::CustomSignalDispositionEvent&
                                                                                event);
        virtual void                            CustomSignalDispositionRemoved(
                                                                        const Team::CustomSignalDispositionEvent&
                                                                                event);

        virtual void                            ConsoleOutputReceived(
                                                                        const Team::ConsoleOutputEvent& event);

        virtual void                            BreakpointAdded(
                                                                        const Team::BreakpointEvent& event);
        virtual void                            BreakpointRemoved(
                                                                        const Team::BreakpointEvent& event);
        virtual void                            UserBreakpointChanged(
                                                                        const Team::UserBreakpointEvent& event);

        virtual void                            WatchpointAdded(
                                                                        const Team::WatchpointEvent& event);
        virtual void                            WatchpointRemoved(
                                                                        const Team::WatchpointEvent& event);
        virtual void                            WatchpointChanged(
                                                                        const Team::WatchpointEvent& event);

        virtual void                            DebugReportChanged(
                                                                        const Team::DebugReportEvent& event);

        virtual void                            CoreFileChanged(
                                                                        const Team::CoreFileChangedEvent& event);

        virtual void                            MemoryChanged(
                                                                        const Team::MemoryChangedEvent& event);
};


#endif  // TEAM_H