Home | History | Annotate | Download | only in MacOSX
      1 //===-- MachProcess.h -------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  Created by Greg Clayton on 6/15/07.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef __MachProcess_h__
     15 #define __MachProcess_h__
     16 
     17 #include "DNBDefs.h"
     18 #include "DNBBreakpoint.h"
     19 #include "DNBError.h"
     20 #include "DNBThreadResumeActions.h"
     21 #include "MachException.h"
     22 #include "MachVMMemory.h"
     23 #include "MachTask.h"
     24 #include "MachThreadList.h"
     25 #include "PThreadCondition.h"
     26 #include "PThreadEvent.h"
     27 #include "PThreadMutex.h"
     28 
     29 #include <mach/mach.h>
     30 #include <sys/signal.h>
     31 #include <pthread.h>
     32 #include <vector>
     33 
     34 class DNBThreadResumeActions;
     35 
     36 class MachProcess
     37 {
     38 public:
     39     //----------------------------------------------------------------------
     40     // Constructors and Destructors
     41     //----------------------------------------------------------------------
     42     MachProcess ();
     43     ~MachProcess ();
     44 
     45     //----------------------------------------------------------------------
     46     // Child process control
     47     //----------------------------------------------------------------------
     48     pid_t                   AttachForDebug (pid_t pid, char *err_str, size_t err_len);
     49     pid_t                   LaunchForDebug (const char *path,
     50                                             char const *argv[],
     51                                             char const *envp[],
     52                                             const char *working_directory,
     53                                             const char *stdin_path,
     54                                             const char *stdout_path,
     55                                             const char *stderr_path,
     56                                             bool no_stdio,
     57                                             nub_launch_flavor_t launch_flavor,
     58                                             int disable_aslr,
     59                                             DNBError &err);
     60 
     61     static uint32_t         GetCPUTypeForLocalProcess (pid_t pid);
     62     static pid_t            ForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], MachProcess* process, DNBError &err);
     63     static pid_t            PosixSpawnChildForPTraceDebugging (const char *path,
     64                                                                cpu_type_t cpu_type,
     65                                                                char const *argv[],
     66                                                                char const *envp[],
     67                                                                const char *working_directory,
     68                                                                const char *stdin_path,
     69                                                                const char *stdout_path,
     70                                                                const char *stderr_path,
     71                                                                bool no_stdio,
     72                                                                MachProcess* process,
     73                                                                int disable_aslr,
     74                                                                DNBError& err);
     75     nub_addr_t              GetDYLDAllImageInfosAddress ();
     76     static const void *     PrepareForAttach (const char *path, nub_launch_flavor_t launch_flavor, bool waitfor, DNBError &err_str);
     77     static void             CleanupAfterAttach (const void *attach_token, bool success, DNBError &err_str);
     78     static nub_process_t    CheckForProcess (const void *attach_token);
     79 #ifdef WITH_SPRINGBOARD
     80     pid_t                   SBLaunchForDebug (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, DNBError &launch_err);
     81     static pid_t            SBForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], bool no_stdio, MachProcess* process, DNBError &launch_err);
     82 #endif
     83     nub_addr_t              LookupSymbol (const char *name, const char *shlib);
     84     void                    SetNameToAddressCallback (DNBCallbackNameToAddress callback, void *baton)
     85                             {
     86                                 m_name_to_addr_callback = callback;
     87                                 m_name_to_addr_baton    = baton;
     88                             }
     89     void                    SetSharedLibraryInfoCallback (DNBCallbackCopyExecutableImageInfos callback, void *baton)
     90                             {
     91                                 m_image_infos_callback    = callback;
     92                                 m_image_infos_baton        = baton;
     93                             }
     94 
     95     bool                    Resume (const DNBThreadResumeActions& thread_actions);
     96     bool                    Signal  (int signal, const struct timespec *timeout_abstime = NULL);
     97     bool                    Kill (const struct timespec *timeout_abstime = NULL);
     98     bool                    Detach ();
     99     nub_size_t              ReadMemory (nub_addr_t addr, nub_size_t size, void *buf);
    100     nub_size_t              WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf);
    101 
    102     //----------------------------------------------------------------------
    103     // Path and arg accessors
    104     //----------------------------------------------------------------------
    105     const char *            Path () const { return m_path.c_str(); }
    106     size_t                  ArgumentCount () const { return m_args.size(); }
    107     const char *            ArgumentAtIndex (size_t arg_idx) const
    108                             {
    109                                 if (arg_idx < m_args.size())
    110                                     return m_args[arg_idx].c_str();
    111                                 return NULL;
    112                             }
    113 
    114     //----------------------------------------------------------------------
    115     // Breakpoint functions
    116     //----------------------------------------------------------------------
    117     DNBBreakpoint *         CreateBreakpoint (nub_addr_t addr, nub_size_t length, bool hardware);
    118     bool                    DisableBreakpoint (nub_addr_t addr, bool remove);
    119     void                    DisableAllBreakpoints (bool remove);
    120     bool                    EnableBreakpoint (nub_addr_t addr);
    121     DNBBreakpointList&      Breakpoints() { return m_breakpoints; }
    122     const DNBBreakpointList& Breakpoints() const { return m_breakpoints; }
    123 
    124     //----------------------------------------------------------------------
    125     // Watchpoint functions
    126     //----------------------------------------------------------------------
    127     DNBBreakpoint *         CreateWatchpoint (nub_addr_t addr, nub_size_t length, uint32_t watch_type, bool hardware);
    128     bool                    DisableWatchpoint (nub_addr_t addr, bool remove);
    129     void                    DisableAllWatchpoints (bool remove);
    130     bool                    EnableWatchpoint (nub_addr_t addr);
    131     uint32_t                GetNumSupportedHardwareWatchpoints () const;
    132     DNBBreakpointList&      Watchpoints() { return m_watchpoints; }
    133     const DNBBreakpointList& Watchpoints() const { return m_watchpoints; }
    134 
    135     //----------------------------------------------------------------------
    136     // Exception thread functions
    137     //----------------------------------------------------------------------
    138     bool                    StartSTDIOThread ();
    139     static void *           STDIOThread (void *arg);
    140     void                    ExceptionMessageReceived (const MachException::Message& exceptionMessage);
    141     void                    ExceptionMessageBundleComplete ();
    142     void                    SharedLibrariesUpdated ();
    143     nub_size_t              CopyImageInfos (struct DNBExecutableImageInfo **image_infos, bool only_changed);
    144 
    145     //----------------------------------------------------------------------
    146     // Profile functions
    147     //----------------------------------------------------------------------
    148     void                    SetEnableAsyncProfiling (bool enable, uint64_t internal_usec, DNBProfileDataScanType scan_type);
    149     bool                    IsProfilingEnabled () { return m_profile_enabled; }
    150     uint64_t                ProfileInterval () { return m_profile_interval_usec; }
    151     bool                    StartProfileThread ();
    152     static void *           ProfileThread (void *arg);
    153     void                    SignalAsyncProfileData (const char *info);
    154     size_t                  GetAsyncProfileData (char *buf, size_t buf_size);
    155 
    156     //----------------------------------------------------------------------
    157     // Accessors
    158     //----------------------------------------------------------------------
    159     pid_t                   ProcessID () const { return m_pid; }
    160     bool                    ProcessIDIsValid () const { return m_pid > 0; }
    161     pid_t                   SetProcessID (pid_t pid);
    162     MachTask&               Task() { return m_task; }
    163     const MachTask&         Task() const { return m_task; }
    164 
    165     PThreadEvent&           Events() { return m_events; }
    166     const DNBRegisterSetInfo *
    167                             GetRegisterSetInfo (nub_thread_t tid, nub_size_t *num_reg_sets) const;
    168     bool                    GetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value) const;
    169     bool                    SetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value) const;
    170     nub_bool_t              SyncThreadState (nub_thread_t tid);
    171     const char *            ThreadGetName (nub_thread_t tid);
    172     nub_state_t             ThreadGetState (nub_thread_t tid);
    173     nub_size_t              GetNumThreads () const;
    174     nub_thread_t            GetThreadAtIndex (nub_size_t thread_idx) const;
    175     nub_thread_t            GetCurrentThread ();
    176     nub_thread_t            GetCurrentThreadMachPort ();
    177     nub_thread_t            SetCurrentThread (nub_thread_t tid);
    178     MachThreadList &        GetThreadList() { return m_thread_list; }
    179     bool                    GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info);
    180     void                    DumpThreadStoppedReason(nub_thread_t tid) const;
    181     const char *            GetThreadInfo (nub_thread_t tid) const;
    182 
    183     nub_thread_t            GetThreadIDForMachPortNumber (thread_t mach_port_number) const;
    184 
    185     uint32_t                GetCPUType ();
    186     nub_state_t             GetState ();
    187     void                    SetState (nub_state_t state);
    188     bool                    IsRunning (nub_state_t state)
    189                             {
    190                                 return    state == eStateRunning || IsStepping(state);
    191                             }
    192     bool                    IsStepping (nub_state_t state)
    193                             {
    194                                 return    state == eStateStepping;
    195                             }
    196     bool                    CanResume (nub_state_t state)
    197                             {
    198                                 return state == eStateStopped;
    199                             }
    200 
    201     bool                    GetExitStatus(int* status)
    202                             {
    203                                 if (GetState() == eStateExited)
    204                                 {
    205                                     if (status)
    206                                         *status = m_exit_status;
    207                                     return true;
    208                                 }
    209                                 return false;
    210                             }
    211     void                    SetExitStatus(int status)
    212                             {
    213                                 m_exit_status = status;
    214                                 SetState(eStateExited);
    215                             }
    216 
    217     uint32_t                StopCount() const { return m_stop_count; }
    218     void                    SetChildFileDescriptors (int stdin_fileno, int stdout_fileno, int stderr_fileno)
    219                             {
    220                                 m_child_stdin   = stdin_fileno;
    221                                 m_child_stdout  = stdout_fileno;
    222                                 m_child_stderr  = stderr_fileno;
    223                             }
    224 
    225     int                     GetStdinFileDescriptor () const { return m_child_stdin; }
    226     int                     GetStdoutFileDescriptor () const { return m_child_stdout; }
    227     int                     GetStderrFileDescriptor () const { return m_child_stderr; }
    228     void                    AppendSTDOUT (char* s, size_t len);
    229     size_t                  GetAvailableSTDOUT (char *buf, size_t buf_size);
    230     size_t                  GetAvailableSTDERR (char *buf, size_t buf_size);
    231     void                    CloseChildFileDescriptors ()
    232                             {
    233                                 if (m_child_stdin >= 0)
    234                                 {
    235                                     ::close (m_child_stdin);
    236                                     m_child_stdin = -1;
    237                                 }
    238                                 if (m_child_stdout >= 0)
    239                                 {
    240                                     ::close (m_child_stdout);
    241                                     m_child_stdout = -1;
    242                                 }
    243                                 if (m_child_stderr >= 0)
    244                                 {
    245                                     ::close (m_child_stderr);
    246                                     m_child_stderr = -1;
    247                                 }
    248                             }
    249 
    250     bool                    ProcessUsingSpringBoard() const { return (m_flags & eMachProcessFlagsUsingSBS) != 0; }
    251 
    252     DNBProfileDataScanType  GetProfileScanType () { return m_profile_scan_type; }
    253 
    254 private:
    255     enum
    256     {
    257         eMachProcessFlagsNone = 0,
    258         eMachProcessFlagsAttached = (1 << 0),
    259         eMachProcessFlagsUsingSBS = (1 << 1)
    260     };
    261     void                    Clear ();
    262     void                    ReplyToAllExceptions ();
    263     void                    PrivateResume ();
    264 
    265     uint32_t                Flags () const { return m_flags; }
    266     nub_state_t             DoSIGSTOP (bool clear_bps_and_wps, bool allow_running, uint32_t *thread_idx_ptr);
    267 
    268     pid_t                       m_pid;                      // Process ID of child process
    269     cpu_type_t                  m_cpu_type;                 // The CPU type of this process
    270     int                         m_child_stdin;
    271     int                         m_child_stdout;
    272     int                         m_child_stderr;
    273     std::string                 m_path;                     // A path to the executable if we have one
    274     std::vector<std::string>    m_args;                     // The arguments with which the process was lauched
    275     int                         m_exit_status;              // The exit status for the process
    276     MachTask                    m_task;                     // The mach task for this process
    277     uint32_t                    m_flags;                    // Process specific flags (see eMachProcessFlags enums)
    278     uint32_t                    m_stop_count;               // A count of many times have we stopped
    279     pthread_t                   m_stdio_thread;             // Thread ID for the thread that watches for child process stdio
    280     PThreadMutex                m_stdio_mutex;              // Multithreaded protection for stdio
    281     std::string                 m_stdout_data;
    282 
    283     bool                        m_profile_enabled;          // A flag to indicate if profiling is enabled
    284     uint64_t                    m_profile_interval_usec;    // If enable, the profiling interval in microseconds
    285     DNBProfileDataScanType      m_profile_scan_type;        // Indicates what needs to be profiled
    286     pthread_t                   m_profile_thread;           // Thread ID for the thread that profiles the inferior
    287     PThreadMutex                m_profile_data_mutex;       // Multithreaded protection for profile info data
    288     std::vector<std::string>    m_profile_data;             // Profile data, must be protected by m_profile_data_mutex
    289 
    290     DNBThreadResumeActions      m_thread_actions;           // The thread actions for the current MachProcess::Resume() call
    291     MachException::Message::collection
    292                                 m_exception_messages;       // A collection of exception messages caught when listening to the exception port
    293     PThreadMutex                m_exception_messages_mutex; // Multithreaded protection for m_exception_messages
    294 
    295     MachThreadList              m_thread_list;               // A list of threads that is maintained/updated after each stop
    296     nub_state_t                 m_state;                    // The state of our process
    297     PThreadMutex                m_state_mutex;              // Multithreaded protection for m_state
    298     PThreadEvent                m_events;                   // Process related events in the child processes lifetime can be waited upon
    299     PThreadEvent                m_private_events;           // Used to coordinate running and stopping the process without affecting m_events
    300     DNBBreakpointList           m_breakpoints;              // Breakpoint list for this process
    301     DNBBreakpointList           m_watchpoints;              // Watchpoint list for this process
    302     DNBCallbackNameToAddress    m_name_to_addr_callback;
    303     void *                      m_name_to_addr_baton;
    304     DNBCallbackCopyExecutableImageInfos
    305                                 m_image_infos_callback;
    306     void *                      m_image_infos_baton;
    307     bool                        m_did_exec;
    308 };
    309 
    310 
    311 #endif // __MachProcess_h__
    312