DNB.cpp revision bd666017403e102e0ca435d6da585ff979f83598
1//===-- DNB.cpp -------------------------------------------------*- 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 3/23/07.
11//
12//===----------------------------------------------------------------------===//
13
14#include "DNB.h"
15#include <signal.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <sys/resource.h>
19#include <sys/stat.h>
20#include <sys/types.h>
21#include <sys/wait.h>
22#include <unistd.h>
23#include <sys/sysctl.h>
24#include <map>
25#include <vector>
26
27#include "MacOSX/MachProcess.h"
28#include "MacOSX/MachTask.h"
29#include "CFString.h"
30#include "DNBLog.h"
31#include "DNBDataRef.h"
32#include "DNBThreadResumeActions.h"
33#include "DNBTimer.h"
34
35typedef std::tr1::shared_ptr<MachProcess> MachProcessSP;
36typedef std::map<nub_process_t, MachProcessSP> ProcessMap;
37typedef ProcessMap::iterator ProcessMapIter;
38typedef ProcessMap::const_iterator ProcessMapConstIter;
39
40static size_t          GetAllInfos                  (std::vector<struct kinfo_proc>& proc_infos);
41static size_t          GetAllInfosMatchingName      (const char *process_name, std::vector<struct kinfo_proc>& matching_proc_infos);
42
43//----------------------------------------------------------------------
44// A Thread safe singleton to get a process map pointer.
45//
46// Returns a pointer to the existing process map, or a pointer to a
47// newly created process map if CAN_CREATE is non-zero.
48//----------------------------------------------------------------------
49static ProcessMap*
50GetProcessMap(bool can_create)
51{
52    static ProcessMap* g_process_map_ptr = NULL;
53
54    if (can_create && g_process_map_ptr == NULL)
55    {
56        static pthread_mutex_t g_process_map_mutex = PTHREAD_MUTEX_INITIALIZER;
57        PTHREAD_MUTEX_LOCKER (locker, &g_process_map_mutex);
58        if (g_process_map_ptr == NULL)
59            g_process_map_ptr = new ProcessMap;
60    }
61    return g_process_map_ptr;
62}
63
64//----------------------------------------------------------------------
65// Add PID to the shared process pointer map.
66//
67// Return non-zero value if we succeed in adding the process to the map.
68// The only time this should fail is if we run out of memory and can't
69// allocate a ProcessMap.
70//----------------------------------------------------------------------
71static nub_bool_t
72AddProcessToMap (nub_process_t pid, MachProcessSP& procSP)
73{
74    ProcessMap* process_map = GetProcessMap(true);
75    if (process_map)
76    {
77        process_map->insert(std::make_pair(pid, procSP));
78        return true;
79    }
80    return false;
81}
82
83//----------------------------------------------------------------------
84// Remove the shared pointer for PID from the process map.
85//
86// Returns the number of items removed from the process map.
87//----------------------------------------------------------------------
88static size_t
89RemoveProcessFromMap (nub_process_t pid)
90{
91    ProcessMap* process_map = GetProcessMap(false);
92    if (process_map)
93    {
94        return process_map->erase(pid);
95    }
96    return 0;
97}
98
99//----------------------------------------------------------------------
100// Get the shared pointer for PID from the existing process map.
101//
102// Returns true if we successfully find a shared pointer to a
103// MachProcess object.
104//----------------------------------------------------------------------
105static nub_bool_t
106GetProcessSP (nub_process_t pid, MachProcessSP& procSP)
107{
108    ProcessMap* process_map = GetProcessMap(false);
109    if (process_map != NULL)
110    {
111        ProcessMapIter pos = process_map->find(pid);
112        if (pos != process_map->end())
113        {
114            procSP = pos->second;
115            return true;
116        }
117    }
118    procSP.reset();
119    return false;
120}
121
122
123static void *
124waitpid_thread (void *arg)
125{
126    const pid_t pid = (pid_t)(intptr_t)arg;
127    int status;
128    while (1)
129    {
130        pid_t child_pid = waitpid(pid, &status, 0);
131        DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): waitpid (pid = %i, &status, 0) => %i, status = %i, errno = %i", pid, child_pid, status, errno);
132
133        if (child_pid < 0)
134        {
135            if (errno == EINTR)
136                continue;
137            break;
138        }
139        else
140        {
141            if (WIFSTOPPED(status))
142            {
143                continue;
144            }
145            else// if (WIFEXITED(status) || WIFSIGNALED(status))
146            {
147                DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, status);
148                DNBProcessSetExitStatus (child_pid, status);
149                return NULL;
150            }
151        }
152    }
153
154    // We should never exit as long as our child process is alive, so if we
155    // do something else went wrong and we should exit...
156    DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): main loop exited, setting exit status to an invalid value (-1) for pid %i", pid);
157    DNBProcessSetExitStatus (pid, -1);
158    return NULL;
159}
160
161static bool
162spawn_waitpid_thread (pid_t pid)
163{
164    pthread_t thread = THREAD_NULL;
165    ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid);
166    if (thread != THREAD_NULL)
167    {
168        ::pthread_detach (thread);
169        return true;
170    }
171    return false;
172}
173
174nub_process_t
175DNBProcessLaunch (const char *path,
176                  char const *argv[],
177                  const char *envp[],
178                  const char *stdio_path,
179                  bool no_stdio,
180                  nub_launch_flavor_t launch_flavor,
181                  int disable_aslr,
182                  char *err_str,
183                  size_t err_len)
184{
185    DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = %zu) called...", __FUNCTION__, path, argv, envp, launch_flavor, disable_aslr, err_str, err_len);
186
187    if (err_str && err_len > 0)
188        err_str[0] = '\0';
189    struct stat path_stat;
190    if (::stat(path, &path_stat) == -1)
191    {
192        char stat_error[256];
193        ::strerror_r (errno, stat_error, sizeof(stat_error));
194        snprintf(err_str, err_len, "%s (%s)", stat_error, path);
195        return INVALID_NUB_PROCESS;
196    }
197
198    MachProcessSP processSP (new MachProcess);
199    if (processSP.get())
200    {
201        DNBError launch_err;
202        pid_t pid = processSP->LaunchForDebug(path, argv, envp, stdio_path, no_stdio, launch_flavor, disable_aslr, launch_err);
203        if (err_str)
204        {
205            *err_str = '\0';
206            if (launch_err.Fail())
207            {
208                const char *launch_err_str = launch_err.AsString();
209                if (launch_err_str)
210                {
211                    strncpy(err_str, launch_err_str, err_len-1);
212                    err_str[err_len-1] = '\0';  // Make sure the error string is terminated
213                }
214            }
215        }
216
217        DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
218
219        if (pid != INVALID_NUB_PROCESS)
220        {
221            // Spawn a thread to reap our child inferior process...
222            spawn_waitpid_thread (pid);
223
224            if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL)
225            {
226                // We failed to get the task for our process ID which is bad.
227                if (err_str && err_len > 0)
228                {
229                    if (launch_err.AsString())
230                    {
231                        ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString());
232                    }
233                    else
234                    {
235                        ::snprintf (err_str, err_len, "failed to get the task for process %i", pid);
236                    }
237                }
238            }
239            else
240            {
241                assert(AddProcessToMap(pid, processSP));
242                return pid;
243            }
244        }
245    }
246    return INVALID_NUB_PROCESS;
247}
248
249nub_process_t
250DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
251{
252    if (err_str && err_len > 0)
253        err_str[0] = '\0';
254    std::vector<struct kinfo_proc> matching_proc_infos;
255    size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
256    if (num_matching_proc_infos == 0)
257    {
258        DNBLogError ("error: no processes match '%s'\n", name);
259        return INVALID_NUB_PROCESS;
260    }
261    else if (num_matching_proc_infos > 1)
262    {
263        DNBLogError ("error: %u processes match '%s':\n", num_matching_proc_infos, name);
264        size_t i;
265        for (i=0; i<num_matching_proc_infos; ++i)
266            DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
267        return INVALID_NUB_PROCESS;
268    }
269
270    return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
271}
272
273nub_process_t
274DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len)
275{
276    if (err_str && err_len > 0)
277        err_str[0] = '\0';
278
279    pid_t pid;
280    MachProcessSP processSP(new MachProcess);
281    if (processSP.get())
282    {
283        DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid);
284        pid = processSP->AttachForDebug (attach_pid, err_str,  err_len);
285
286        if (pid != INVALID_NUB_PROCESS)
287        {
288            assert(AddProcessToMap(pid, processSP));
289            spawn_waitpid_thread(pid);
290        }
291    }
292
293    while (pid != INVALID_NUB_PROCESS)
294    {
295        // Wait for process to start up and hit entry point
296        DNBLogThreadedIf (LOG_PROCESS,
297                          "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
298                          __FUNCTION__,
299                          pid);
300        nub_event_t set_events = DNBProcessWaitForEvents (pid,
301                                                          eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
302                                                          true,
303                                                          timeout);
304
305        DNBLogThreadedIf (LOG_PROCESS,
306                          "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
307                          __FUNCTION__,
308                          pid,
309                          set_events);
310
311        if (set_events == 0)
312        {
313            if (err_str && err_len > 0)
314                snprintf(err_str, err_len, "operation timed out");
315            pid = INVALID_NUB_PROCESS;
316        }
317        else
318        {
319            if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
320            {
321                nub_state_t pid_state = DNBProcessGetState (pid);
322                DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s",
323                        __FUNCTION__, pid, DNBStateAsString(pid_state));
324
325                switch (pid_state)
326                {
327                    default:
328                    case eStateInvalid:
329                    case eStateUnloaded:
330                    case eStateAttaching:
331                    case eStateLaunching:
332                    case eStateSuspended:
333                        break;  // Ignore
334
335                    case eStateRunning:
336                    case eStateStepping:
337                        // Still waiting to stop at entry point...
338                        break;
339
340                    case eStateStopped:
341                    case eStateCrashed:
342                        return pid;
343
344                    case eStateDetached:
345                    case eStateExited:
346                        if (err_str && err_len > 0)
347                            snprintf(err_str, err_len, "process exited");
348                        return INVALID_NUB_PROCESS;
349                }
350            }
351
352            DNBProcessResetEvents(pid, set_events);
353        }
354    }
355
356    return INVALID_NUB_PROCESS;
357}
358
359static size_t
360GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
361{
362    size_t size;
363    int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
364    u_int namelen = sizeof(name)/sizeof(int);
365    int err;
366
367    // Try to find out how many processes are around so we can
368    // size the buffer appropriately.  sysctl's man page specifically suggests
369    // this approach, and says it returns a bit larger size than needed to
370    // handle any new processes created between then and now.
371
372    err = ::sysctl (name, namelen, NULL, &size, NULL, 0);
373
374    if ((err < 0) && (err != ENOMEM))
375    {
376        proc_infos.clear();
377        perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
378        return 0;
379    }
380
381
382    // Increase the size of the buffer by a few processes in case more have
383    // been spawned
384    proc_infos.resize (size / sizeof(struct kinfo_proc));
385    size = proc_infos.size() * sizeof(struct kinfo_proc);   // Make sure we don't exceed our resize...
386    err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0);
387    if (err < 0)
388    {
389        proc_infos.clear();
390        return 0;
391    }
392
393    // Trim down our array to fit what we actually got back
394    proc_infos.resize(size / sizeof(struct kinfo_proc));
395    return proc_infos.size();
396}
397
398
399static size_t
400GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos)
401{
402
403    matching_proc_infos.clear();
404    if (full_process_name && full_process_name[0])
405    {
406        // We only get the process name, not the full path, from the proc_info.  So just take the
407        // base name of the process name...
408        const char *process_name;
409        process_name = strrchr (full_process_name, '/');
410        if (process_name == NULL)
411          process_name = full_process_name;
412        else
413          process_name++;
414
415        std::vector<struct kinfo_proc> proc_infos;
416        const size_t num_proc_infos = GetAllInfos(proc_infos);
417        if (num_proc_infos > 0)
418        {
419            uint32_t i;
420            for (i=0; i<num_proc_infos; i++)
421            {
422                // Skip zombie processes and processes with unset status
423                if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB)
424                    continue;
425
426                // Check for process by name. We only check the first MAXCOMLEN
427                // chars as that is all that kp_proc.p_comm holds.
428                if (::strncasecmp(proc_infos[i].kp_proc.p_comm, process_name, MAXCOMLEN) == 0)
429                {
430                    // We found a matching process, add it to our list
431                    matching_proc_infos.push_back(proc_infos[i]);
432                }
433            }
434        }
435    }
436    // return the newly added matches.
437    return matching_proc_infos.size();
438}
439
440nub_process_t
441DNBProcessAttachWait (const char *waitfor_process_name,
442                      nub_launch_flavor_t launch_flavor,
443                      struct timespec *timeout_abstime,
444                      useconds_t waitfor_interval,
445                      char *err_str,
446                      size_t err_len,
447                      DNBShouldCancelCallback should_cancel_callback,
448                      void *callback_data)
449{
450    DNBError prepare_error;
451    std::vector<struct kinfo_proc> exclude_proc_infos;
452    size_t num_exclude_proc_infos;
453
454    // If the PrepareForAttach returns a valid token, use  MachProcess to check
455    // for the process, otherwise scan the process table.
456
457    const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error);
458
459    if (prepare_error.Fail())
460    {
461        DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString());
462        return INVALID_NUB_PROCESS;
463    }
464
465    if (attach_token == NULL)
466        num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
467
468    DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
469
470    // Loop and try to find the process by name
471    nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
472
473    while (waitfor_pid == INVALID_NUB_PROCESS)
474    {
475        if (attach_token != NULL)
476        {
477            nub_process_t pid;
478            pid = MachProcess::CheckForProcess(attach_token);
479            if (pid != INVALID_NUB_PROCESS)
480            {
481                waitfor_pid = pid;
482                break;
483            }
484        }
485        else
486        {
487
488            // Get the current process list, and check for matches that
489            // aren't in our original list. If anyone wants to attach
490            // to an existing process by name, they should do it with
491            // --attach=PROCNAME. Else we will wait for the first matching
492            // process that wasn't in our exclusion list.
493            std::vector<struct kinfo_proc> proc_infos;
494            const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos);
495            for (size_t i=0; i<num_proc_infos; i++)
496            {
497                nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
498                for (size_t j=0; j<num_exclude_proc_infos; j++)
499                {
500                    if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid)
501                    {
502                        // This process was in our exclusion list, don't use it.
503                        curr_pid = INVALID_NUB_PROCESS;
504                        break;
505                    }
506                }
507
508                // If we didn't find CURR_PID in our exclusion list, then use it.
509                if (curr_pid != INVALID_NUB_PROCESS)
510                {
511                    // We found our process!
512                    waitfor_pid = curr_pid;
513                    break;
514                }
515            }
516        }
517
518        // If we haven't found our process yet, check for a timeout
519        // and then sleep for a bit until we poll again.
520        if (waitfor_pid == INVALID_NUB_PROCESS)
521        {
522            if (timeout_abstime != NULL)
523            {
524                // Check to see if we have a waitfor-duration option that
525                // has timed out?
526                if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime))
527                {
528                    if (err_str && err_len > 0)
529                        snprintf(err_str, err_len, "operation timed out");
530                    DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name);
531                    return INVALID_NUB_PROCESS;
532                }
533            }
534
535            // Call the should cancel callback as well...
536
537            if (should_cancel_callback != NULL
538                && should_cancel_callback (callback_data))
539            {
540                DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback.");
541                waitfor_pid = INVALID_NUB_PROCESS;
542                break;
543            }
544
545            ::usleep (waitfor_interval);    // Sleep for WAITFOR_INTERVAL, then poll again
546        }
547    }
548
549    if (waitfor_pid != INVALID_NUB_PROCESS)
550    {
551        DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid);
552        waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len);
553    }
554
555    bool success = waitfor_pid != INVALID_NUB_PROCESS;
556    MachProcess::CleanupAfterAttach (attach_token, success, prepare_error);
557
558    return waitfor_pid;
559}
560
561nub_bool_t
562DNBProcessDetach (nub_process_t pid)
563{
564    MachProcessSP procSP;
565    if (GetProcessSP (pid, procSP))
566    {
567        return procSP->Detach();
568    }
569    return false;
570}
571
572nub_bool_t
573DNBProcessKill (nub_process_t pid)
574{
575    MachProcessSP procSP;
576    if (GetProcessSP (pid, procSP))
577    {
578        return procSP->Kill ();
579    }
580    return false;
581}
582
583nub_bool_t
584DNBProcessSignal (nub_process_t pid, int signal)
585{
586    MachProcessSP procSP;
587    if (GetProcessSP (pid, procSP))
588    {
589        return procSP->Signal (signal);
590    }
591    return false;
592}
593
594
595nub_bool_t
596DNBProcessIsAlive (nub_process_t pid)
597{
598    MachProcessSP procSP;
599    if (GetProcessSP (pid, procSP))
600    {
601        return MachTask::IsValid (procSP->Task().TaskPort());
602    }
603    return eStateInvalid;
604}
605
606//----------------------------------------------------------------------
607// Process and Thread state information
608//----------------------------------------------------------------------
609nub_state_t
610DNBProcessGetState (nub_process_t pid)
611{
612    MachProcessSP procSP;
613    if (GetProcessSP (pid, procSP))
614    {
615        return procSP->GetState();
616    }
617    return eStateInvalid;
618}
619
620//----------------------------------------------------------------------
621// Process and Thread state information
622//----------------------------------------------------------------------
623nub_bool_t
624DNBProcessGetExitStatus (nub_process_t pid, int* status)
625{
626    MachProcessSP procSP;
627    if (GetProcessSP (pid, procSP))
628    {
629        return procSP->GetExitStatus(status);
630    }
631    return false;
632}
633
634nub_bool_t
635DNBProcessSetExitStatus (nub_process_t pid, int status)
636{
637    MachProcessSP procSP;
638    if (GetProcessSP (pid, procSP))
639    {
640        procSP->SetExitStatus(status);
641        return true;
642    }
643    return false;
644}
645
646
647const char *
648DNBThreadGetName (nub_process_t pid, nub_thread_t tid)
649{
650    MachProcessSP procSP;
651    if (GetProcessSP (pid, procSP))
652        return procSP->ThreadGetName(tid);
653    return NULL;
654}
655
656
657nub_bool_t
658DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info)
659{
660    MachProcessSP procSP;
661    if (GetProcessSP (pid, procSP))
662        return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
663    return false;
664}
665
666nub_state_t
667DNBThreadGetState (nub_process_t pid, nub_thread_t tid)
668{
669    MachProcessSP procSP;
670    if (GetProcessSP (pid, procSP))
671    {
672        return procSP->ThreadGetState(tid);
673    }
674    return eStateInvalid;
675}
676
677const char *
678DNBStateAsString(nub_state_t state)
679{
680    switch (state)
681    {
682    case eStateUnloaded:    return "Unloaded";
683    case eStateAttaching:   return "Attaching";
684    case eStateLaunching:   return "Launching";
685    case eStateStopped:     return "Stopped";
686    case eStateRunning:     return "Running";
687    case eStateStepping:    return "Stepping";
688    case eStateCrashed:     return "Crashed";
689    case eStateDetached:    return "Detached";
690    case eStateExited:      return "Exited";
691    case eStateSuspended:   return "Suspended";
692    }
693    return "nub_state_t ???";
694}
695
696const char *
697DNBProcessGetExecutablePath (nub_process_t pid)
698{
699    MachProcessSP procSP;
700    if (GetProcessSP (pid, procSP))
701    {
702        return procSP->Path();
703    }
704    return NULL;
705}
706
707nub_size_t
708DNBProcessGetArgumentCount (nub_process_t pid)
709{
710    MachProcessSP procSP;
711    if (GetProcessSP (pid, procSP))
712    {
713        return procSP->ArgumentCount();
714    }
715    return 0;
716}
717
718const char *
719DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx)
720{
721    MachProcessSP procSP;
722    if (GetProcessSP (pid, procSP))
723    {
724        return procSP->ArgumentAtIndex (idx);
725    }
726    return NULL;
727}
728
729
730//----------------------------------------------------------------------
731// Execution control
732//----------------------------------------------------------------------
733nub_bool_t
734DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions)
735{
736    DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
737    MachProcessSP procSP;
738    if (GetProcessSP (pid, procSP))
739    {
740        DNBThreadResumeActions thread_actions (actions, num_actions);
741
742        // Below we add a default thread plan just in case one wasn't
743        // provided so all threads always know what they were supposed to do
744        if (thread_actions.IsEmpty())
745        {
746            // No thread plans were given, so the default it to run all threads
747            thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
748        }
749        else
750        {
751            // Some thread plans were given which means anything that wasn't
752            // specified should remain stopped.
753            thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
754        }
755        return procSP->Resume (thread_actions);
756    }
757    return false;
758}
759
760nub_bool_t
761DNBProcessHalt (nub_process_t pid)
762{
763    DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
764    MachProcessSP procSP;
765    if (GetProcessSP (pid, procSP))
766        return procSP->Signal (SIGSTOP);
767    return false;
768}
769//
770//nub_bool_t
771//DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
772//{
773//    DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step);
774//    MachProcessSP procSP;
775//    if (GetProcessSP (pid, procSP))
776//    {
777//        return procSP->Resume(tid, step, 0);
778//    }
779//    return false;
780//}
781//
782//nub_bool_t
783//DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal)
784//{
785//    DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
786//    MachProcessSP procSP;
787//    if (GetProcessSP (pid, procSP))
788//    {
789//        return procSP->Resume(tid, step, signal);
790//    }
791//    return false;
792//}
793
794nub_event_t
795DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout)
796{
797    nub_event_t result = 0;
798    MachProcessSP procSP;
799    if (GetProcessSP (pid, procSP))
800    {
801        if (wait_for_set)
802            result = procSP->Events().WaitForSetEvents(event_mask, timeout);
803        else
804            result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
805    }
806    return result;
807}
808
809void
810DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask)
811{
812    MachProcessSP procSP;
813    if (GetProcessSP (pid, procSP))
814        procSP->Events().ResetEvents(event_mask);
815}
816
817void
818DNBProcessInterruptEvents (nub_process_t pid)
819{
820    MachProcessSP procSP;
821    if (GetProcessSP (pid, procSP))
822        procSP->Events().SetEvents(eEventProcessAsyncInterrupt);
823}
824
825
826// Breakpoints
827nub_break_t
828DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
829{
830    MachProcessSP procSP;
831    if (GetProcessSP (pid, procSP))
832    {
833        return procSP->CreateBreakpoint(addr, size, hardware, THREAD_NULL);
834    }
835    return INVALID_NUB_BREAK_ID;
836}
837
838nub_bool_t
839DNBBreakpointClear (nub_process_t pid, nub_break_t breakID)
840{
841    if (NUB_BREAK_ID_IS_VALID(breakID))
842    {
843        MachProcessSP procSP;
844        if (GetProcessSP (pid, procSP))
845        {
846            return procSP->DisableBreakpoint(breakID, true);
847        }
848    }
849    return false; // Failed
850}
851
852nub_ssize_t
853DNBBreakpointGetHitCount (nub_process_t pid, nub_break_t breakID)
854{
855    if (NUB_BREAK_ID_IS_VALID(breakID))
856    {
857        MachProcessSP procSP;
858        if (GetProcessSP (pid, procSP))
859        {
860            DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID);
861            if (bp)
862                return bp->GetHitCount();
863        }
864    }
865    return 0;
866}
867
868nub_ssize_t
869DNBBreakpointGetIgnoreCount (nub_process_t pid, nub_break_t breakID)
870{
871    if (NUB_BREAK_ID_IS_VALID(breakID))
872    {
873        MachProcessSP procSP;
874        if (GetProcessSP (pid, procSP))
875        {
876            DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID);
877            if (bp)
878                return bp->GetIgnoreCount();
879        }
880    }
881    return 0;
882}
883
884nub_bool_t
885DNBBreakpointSetIgnoreCount (nub_process_t pid, nub_break_t breakID, nub_size_t ignore_count)
886{
887    if (NUB_BREAK_ID_IS_VALID(breakID))
888    {
889        MachProcessSP procSP;
890        if (GetProcessSP (pid, procSP))
891        {
892            DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID);
893            if (bp)
894            {
895                bp->SetIgnoreCount(ignore_count);
896                return true;
897            }
898        }
899    }
900    return false;
901}
902
903// Set the callback function for a given breakpoint. The callback function will
904// get called as soon as the breakpoint is hit. The function will be called
905// with the process ID, thread ID, breakpoint ID and the baton, and can return
906//
907nub_bool_t
908DNBBreakpointSetCallback (nub_process_t pid, nub_break_t breakID, DNBCallbackBreakpointHit callback, void *baton)
909{
910    if (NUB_BREAK_ID_IS_VALID(breakID))
911    {
912        MachProcessSP procSP;
913        if (GetProcessSP (pid, procSP))
914        {
915            DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID);
916            if (bp)
917            {
918                bp->SetCallback(callback, baton);
919                return true;
920            }
921        }
922    }
923    return false;
924}
925
926//----------------------------------------------------------------------
927// Dump the breakpoints stats for process PID for a breakpoint by ID.
928//----------------------------------------------------------------------
929void
930DNBBreakpointPrint (nub_process_t pid, nub_break_t breakID)
931{
932    MachProcessSP procSP;
933    if (GetProcessSP (pid, procSP))
934        procSP->DumpBreakpoint(breakID);
935}
936
937//----------------------------------------------------------------------
938// Watchpoints
939//----------------------------------------------------------------------
940nub_watch_t
941DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware)
942{
943    MachProcessSP procSP;
944    if (GetProcessSP (pid, procSP))
945    {
946        return procSP->CreateWatchpoint(addr, size, watch_flags, hardware, THREAD_NULL);
947    }
948    return INVALID_NUB_BREAK_ID;
949}
950
951nub_bool_t
952DNBWatchpointClear (nub_process_t pid, nub_watch_t watchID)
953{
954    if (NUB_BREAK_ID_IS_VALID(watchID))
955    {
956        MachProcessSP procSP;
957        if (GetProcessSP (pid, procSP))
958        {
959            return procSP->DisableWatchpoint(watchID, true);
960        }
961    }
962    return false; // Failed
963}
964
965nub_ssize_t
966DNBWatchpointGetHitCount (nub_process_t pid, nub_watch_t watchID)
967{
968    if (NUB_BREAK_ID_IS_VALID(watchID))
969    {
970        MachProcessSP procSP;
971        if (GetProcessSP (pid, procSP))
972        {
973            DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID);
974            if (bp)
975                return bp->GetHitCount();
976        }
977    }
978    return 0;
979}
980
981nub_ssize_t
982DNBWatchpointGetIgnoreCount (nub_process_t pid, nub_watch_t watchID)
983{
984    if (NUB_BREAK_ID_IS_VALID(watchID))
985    {
986        MachProcessSP procSP;
987        if (GetProcessSP (pid, procSP))
988        {
989            DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID);
990            if (bp)
991                return bp->GetIgnoreCount();
992        }
993    }
994    return 0;
995}
996
997nub_bool_t
998DNBWatchpointSetIgnoreCount (nub_process_t pid, nub_watch_t watchID, nub_size_t ignore_count)
999{
1000    if (NUB_BREAK_ID_IS_VALID(watchID))
1001    {
1002        MachProcessSP procSP;
1003        if (GetProcessSP (pid, procSP))
1004        {
1005            DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID);
1006            if (bp)
1007            {
1008                bp->SetIgnoreCount(ignore_count);
1009                return true;
1010            }
1011        }
1012    }
1013    return false;
1014}
1015
1016// Set the callback function for a given watchpoint. The callback function will
1017// get called as soon as the watchpoint is hit. The function will be called
1018// with the process ID, thread ID, watchpoint ID and the baton, and can return
1019//
1020nub_bool_t
1021DNBWatchpointSetCallback (nub_process_t pid, nub_watch_t watchID, DNBCallbackBreakpointHit callback, void *baton)
1022{
1023    if (NUB_BREAK_ID_IS_VALID(watchID))
1024    {
1025        MachProcessSP procSP;
1026        if (GetProcessSP (pid, procSP))
1027        {
1028            DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID);
1029            if (bp)
1030            {
1031                bp->SetCallback(callback, baton);
1032                return true;
1033            }
1034        }
1035    }
1036    return false;
1037}
1038
1039//----------------------------------------------------------------------
1040// Dump the watchpoints stats for process PID for a watchpoint by ID.
1041//----------------------------------------------------------------------
1042void
1043DNBWatchpointPrint (nub_process_t pid, nub_watch_t watchID)
1044{
1045    MachProcessSP procSP;
1046    if (GetProcessSP (pid, procSP))
1047        procSP->DumpWatchpoint(watchID);
1048}
1049
1050//----------------------------------------------------------------------
1051// Read memory in the address space of process PID. This call will take
1052// care of setting and restoring permissions and breaking up the memory
1053// read into multiple chunks as required.
1054//
1055// RETURNS: number of bytes actually read
1056//----------------------------------------------------------------------
1057nub_size_t
1058DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf)
1059{
1060    MachProcessSP procSP;
1061    if (GetProcessSP (pid, procSP))
1062        return procSP->ReadMemory(addr, size, buf);
1063    return 0;
1064}
1065
1066//----------------------------------------------------------------------
1067// Write memory to the address space of process PID. This call will take
1068// care of setting and restoring permissions and breaking up the memory
1069// write into multiple chunks as required.
1070//
1071// RETURNS: number of bytes actually written
1072//----------------------------------------------------------------------
1073nub_size_t
1074DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf)
1075{
1076    MachProcessSP procSP;
1077    if (GetProcessSP (pid, procSP))
1078        return procSP->WriteMemory(addr, size, buf);
1079    return 0;
1080}
1081
1082nub_addr_t
1083DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions)
1084{
1085    MachProcessSP procSP;
1086    if (GetProcessSP (pid, procSP))
1087        return procSP->Task().AllocateMemory (size, permissions);
1088    return 0;
1089}
1090
1091nub_bool_t
1092DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr)
1093{
1094    MachProcessSP procSP;
1095    if (GetProcessSP (pid, procSP))
1096        return procSP->Task().DeallocateMemory (addr);
1097    return 0;
1098}
1099
1100
1101//----------------------------------------------------------------------
1102// Formatted output that uses memory and registers from process and
1103// thread in place of arguments.
1104//----------------------------------------------------------------------
1105nub_size_t
1106DNBPrintf (nub_process_t pid, nub_thread_t tid, nub_addr_t base_addr, FILE *file, const char *format)
1107{
1108    if (file == NULL)
1109        return 0;
1110    enum printf_flags
1111    {
1112        alternate_form          = (1 << 0),
1113        zero_padding            = (1 << 1),
1114        negative_field_width    = (1 << 2),
1115        blank_space             = (1 << 3),
1116        show_sign               = (1 << 4),
1117        show_thousands_separator= (1 << 5),
1118    };
1119
1120    enum printf_length_modifiers
1121    {
1122        length_mod_h            = (1 << 0),
1123        length_mod_hh           = (1 << 1),
1124        length_mod_l            = (1 << 2),
1125        length_mod_ll           = (1 << 3),
1126        length_mod_L            = (1 << 4),
1127        length_mod_j            = (1 << 5),
1128        length_mod_t            = (1 << 6),
1129        length_mod_z            = (1 << 7),
1130        length_mod_q            = (1 << 8),
1131    };
1132
1133    nub_addr_t addr = base_addr;
1134    char *end_format = (char*)format + strlen(format);
1135    char *end = NULL;    // For strtoXXXX calls;
1136    std::basic_string<uint8_t> buf;
1137    nub_size_t total_bytes_read = 0;
1138    DNBDataRef data;
1139    const char *f;
1140    for (f = format; *f != '\0' && f < end_format; f++)
1141    {
1142        char ch = *f;
1143        switch (ch)
1144        {
1145        case '%':
1146            {
1147                f++;    // Skip the '%' character
1148                int min_field_width = 0;
1149                int precision = 0;
1150                uint32_t flags = 0;
1151                uint32_t length_modifiers = 0;
1152                uint32_t byte_size = 0;
1153                uint32_t actual_byte_size = 0;
1154                bool is_string = false;
1155                bool is_register = false;
1156                DNBRegisterValue register_value;
1157                int64_t    register_offset = 0;
1158                nub_addr_t register_addr = INVALID_NUB_ADDRESS;
1159
1160                // Create the format string to use for this conversion specification
1161                // so we can remove and mprintf specific flags and formatters.
1162                std::string fprintf_format("%");
1163
1164                // Decode any flags
1165                switch (*f)
1166                {
1167                case '#': fprintf_format += *f++; flags |= alternate_form;            break;
1168                case '0': fprintf_format += *f++; flags |= zero_padding;            break;
1169                case '-': fprintf_format += *f++; flags |= negative_field_width;    break;
1170                case ' ': fprintf_format += *f++; flags |= blank_space;                break;
1171                case '+': fprintf_format += *f++; flags |= show_sign;                break;
1172                case ',': fprintf_format += *f++; flags |= show_thousands_separator;break;
1173                case '{':
1174                case '[':
1175                    {
1176                        // We have a register name specification that can take two forms:
1177                        // ${regname} or ${regname+offset}
1178                        //        The action is to read the register value and add the signed offset
1179                        //        (if any) and use that as the value to format.
1180                        // $[regname] or $[regname+offset]
1181                        //        The action is to read the register value and add the signed offset
1182                        //        (if any) and use the result as an address to dereference. The size
1183                        //        of what is dereferenced is specified by the actual byte size that
1184                        //        follows the minimum field width and precision (see comments below).
1185                        switch (*f)
1186                        {
1187                        case '{':
1188                        case '[':
1189                            {
1190                                char open_scope_ch = *f;
1191                                f++;
1192                                const char *reg_name = f;
1193                                size_t reg_name_length = strcspn(f, "+-}]");
1194                                if (reg_name_length > 0)
1195                                {
1196                                    std::string register_name(reg_name, reg_name_length);
1197                                    f += reg_name_length;
1198                                    register_offset = strtoll(f, &end, 0);
1199                                    if (f < end)
1200                                        f = end;
1201                                    if ((open_scope_ch == '{' && *f != '}') || (open_scope_ch == '[' && *f != ']'))
1202                                    {
1203                                        fprintf(file, "error: Invalid register format string. Valid formats are %%{regname} or %%{regname+offset}, %%[regname] or %%[regname+offset]\n");
1204                                        return total_bytes_read;
1205                                    }
1206                                    else
1207                                    {
1208                                        f++;
1209                                        if (DNBThreadGetRegisterValueByName(pid, tid, REGISTER_SET_ALL, register_name.c_str(), &register_value))
1210                                        {
1211                                            // Set the address to dereference using the register value plus the offset
1212                                            switch (register_value.info.size)
1213                                            {
1214                                            default:
1215                                            case 0:
1216                                                fprintf (file, "error: unsupported register size of %u.\n", register_value.info.size);
1217                                                return total_bytes_read;
1218
1219                                            case 1:        register_addr = register_value.value.uint8  + register_offset; break;
1220                                            case 2:        register_addr = register_value.value.uint16 + register_offset; break;
1221                                            case 4:        register_addr = register_value.value.uint32 + register_offset; break;
1222                                            case 8:        register_addr = register_value.value.uint64 + register_offset; break;
1223                                            case 16:
1224                                                if (open_scope_ch == '[')
1225                                                {
1226                                                    fprintf (file, "error: register size (%u) too large for address.\n", register_value.info.size);
1227                                                    return total_bytes_read;
1228                                                }
1229                                                break;
1230                                            }
1231
1232                                            if (open_scope_ch == '{')
1233                                            {
1234                                                byte_size = register_value.info.size;
1235                                                is_register = true;    // value is in a register
1236
1237                                            }
1238                                            else
1239                                            {
1240                                                addr = register_addr;    // Use register value and offset as the address
1241                                            }
1242                                        }
1243                                        else
1244                                        {
1245                                            fprintf(file, "error: unable to read register '%s' for process %#.4x and thread %#.4x\n", register_name.c_str(), pid, tid);
1246                                            return total_bytes_read;
1247                                        }
1248                                    }
1249                                }
1250                            }
1251                            break;
1252
1253                        default:
1254                            fprintf(file, "error: %%$ must be followed by (regname + n) or [regname + n]\n");
1255                            return total_bytes_read;
1256                        }
1257                    }
1258                    break;
1259                }
1260
1261                // Check for a minimum field width
1262                if (isdigit(*f))
1263                {
1264                    min_field_width = strtoul(f, &end, 10);
1265                    if (end > f)
1266                    {
1267                        fprintf_format.append(f, end - f);
1268                        f = end;
1269                    }
1270                }
1271
1272
1273                // Check for a precision
1274                if (*f == '.')
1275                {
1276                    f++;
1277                    if (isdigit(*f))
1278                    {
1279                        fprintf_format += '.';
1280                        precision = strtoul(f, &end, 10);
1281                        if (end > f)
1282                        {
1283                            fprintf_format.append(f, end - f);
1284                            f = end;
1285                        }
1286                    }
1287                }
1288
1289
1290                // mprintf specific: read the optional actual byte size (abs)
1291                // after the standard minimum field width (mfw) and precision (prec).
1292                // Standard printf calls you can have "mfw.prec" or ".prec", but
1293                // mprintf can have "mfw.prec.abs", ".prec.abs" or "..abs". This is nice
1294                // for strings that may be in a fixed size buffer, but may not use all bytes
1295                // in that buffer for printable characters.
1296                if (*f == '.')
1297                {
1298                    f++;
1299                    actual_byte_size = strtoul(f, &end, 10);
1300                    if (end > f)
1301                    {
1302                        byte_size = actual_byte_size;
1303                        f = end;
1304                    }
1305                }
1306
1307                // Decode the length modifiers
1308                switch (*f)
1309                {
1310                case 'h':    // h and hh length modifiers
1311                    fprintf_format += *f++;
1312                    length_modifiers |= length_mod_h;
1313                    if (*f == 'h')
1314                    {
1315                        fprintf_format += *f++;
1316                        length_modifiers |= length_mod_hh;
1317                    }
1318                    break;
1319
1320                case 'l': // l and ll length modifiers
1321                    fprintf_format += *f++;
1322                    length_modifiers |= length_mod_l;
1323                    if (*f == 'h')
1324                    {
1325                        fprintf_format += *f++;
1326                        length_modifiers |= length_mod_ll;
1327                    }
1328                    break;
1329
1330                case 'L':    fprintf_format += *f++;    length_modifiers |= length_mod_L;    break;
1331                case 'j':    fprintf_format += *f++;    length_modifiers |= length_mod_j;    break;
1332                case 't':    fprintf_format += *f++;    length_modifiers |= length_mod_t;    break;
1333                case 'z':    fprintf_format += *f++;    length_modifiers |= length_mod_z;    break;
1334                case 'q':    fprintf_format += *f++;    length_modifiers |= length_mod_q;    break;
1335                }
1336
1337                // Decode the conversion specifier
1338                switch (*f)
1339                {
1340                case '_':
1341                    // mprintf specific format items
1342                    {
1343                        ++f;    // Skip the '_' character
1344                        switch (*f)
1345                        {
1346                        case 'a':    // Print the current address
1347                            ++f;
1348                            fprintf_format += "ll";
1349                            fprintf_format += *f;    // actual format to show address with folows the 'a' ("%_ax")
1350                            fprintf (file, fprintf_format.c_str(), addr);
1351                            break;
1352                        case 'o':    // offset from base address
1353                            ++f;
1354                            fprintf_format += "ll";
1355                            fprintf_format += *f;    // actual format to show address with folows the 'a' ("%_ox")
1356                            fprintf(file, fprintf_format.c_str(), addr - base_addr);
1357                            break;
1358                        default:
1359                            fprintf (file, "error: unsupported mprintf specific format character '%c'.\n", *f);
1360                            break;
1361                        }
1362                        continue;
1363                    }
1364                    break;
1365
1366                case 'D':
1367                case 'O':
1368                case 'U':
1369                    fprintf_format += *f;
1370                    if (byte_size == 0)
1371                        byte_size = sizeof(long int);
1372                    break;
1373
1374                case 'd':
1375                case 'i':
1376                case 'o':
1377                case 'u':
1378                case 'x':
1379                case 'X':
1380                    fprintf_format += *f;
1381                    if (byte_size == 0)
1382                    {
1383                        if (length_modifiers & length_mod_hh)
1384                            byte_size = sizeof(char);
1385                        else if (length_modifiers & length_mod_h)
1386                            byte_size = sizeof(short);
1387                        if (length_modifiers & length_mod_ll)
1388                            byte_size = sizeof(long long);
1389                        else if (length_modifiers & length_mod_l)
1390                            byte_size = sizeof(long);
1391                        else
1392                            byte_size = sizeof(int);
1393                    }
1394                    break;
1395
1396                case 'a':
1397                case 'A':
1398                case 'f':
1399                case 'F':
1400                case 'e':
1401                case 'E':
1402                case 'g':
1403                case 'G':
1404                    fprintf_format += *f;
1405                    if (byte_size == 0)
1406                    {
1407                        if (length_modifiers & length_mod_L)
1408                            byte_size = sizeof(long double);
1409                        else
1410                            byte_size = sizeof(double);
1411                    }
1412                    break;
1413
1414                case 'c':
1415                    if ((length_modifiers & length_mod_l) == 0)
1416                    {
1417                        fprintf_format += *f;
1418                        if (byte_size == 0)
1419                            byte_size = sizeof(char);
1420                        break;
1421                    }
1422                    // Fall through to 'C' modifier below...
1423
1424                case 'C':
1425                    fprintf_format += *f;
1426                    if (byte_size == 0)
1427                        byte_size = sizeof(wchar_t);
1428                    break;
1429
1430                case 's':
1431                    fprintf_format += *f;
1432                    if (is_register || byte_size == 0)
1433                        is_string = 1;
1434                    break;
1435
1436                case 'p':
1437                    fprintf_format += *f;
1438                    if (byte_size == 0)
1439                        byte_size = sizeof(void*);
1440                    break;
1441                }
1442
1443                if (is_string)
1444                {
1445                    std::string mem_string;
1446                    const size_t string_buf_len = 4;
1447                    char string_buf[string_buf_len+1];
1448                    char *string_buf_end = string_buf + string_buf_len;
1449                    string_buf[string_buf_len] = '\0';
1450                    nub_size_t bytes_read;
1451                    nub_addr_t str_addr = is_register ? register_addr : addr;
1452                    while ((bytes_read = DNBProcessMemoryRead(pid, str_addr, string_buf_len, &string_buf[0])) > 0)
1453                    {
1454                        // Did we get a NULL termination character yet?
1455                        if (strchr(string_buf, '\0') == string_buf_end)
1456                        {
1457                            // no NULL terminator yet, append as a std::string
1458                            mem_string.append(string_buf, string_buf_len);
1459                            str_addr += string_buf_len;
1460                        }
1461                        else
1462                        {
1463                            // yep
1464                            break;
1465                        }
1466                    }
1467                    // Append as a C-string so we don't get the extra NULL
1468                    // characters in the temp buffer (since it was resized)
1469                    mem_string += string_buf;
1470                    size_t mem_string_len = mem_string.size() + 1;
1471                    fprintf(file, fprintf_format.c_str(), mem_string.c_str());
1472                    if (mem_string_len > 0)
1473                    {
1474                        if (!is_register)
1475                        {
1476                            addr += mem_string_len;
1477                            total_bytes_read += mem_string_len;
1478                        }
1479                    }
1480                    else
1481                        return total_bytes_read;
1482                }
1483                else
1484                if (byte_size > 0)
1485                {
1486                    buf.resize(byte_size);
1487                    nub_size_t bytes_read = 0;
1488                    if (is_register)
1489                        bytes_read = register_value.info.size;
1490                    else
1491                        bytes_read = DNBProcessMemoryRead(pid, addr, buf.size(), &buf[0]);
1492                    if (bytes_read > 0)
1493                    {
1494                        if (!is_register)
1495                            total_bytes_read += bytes_read;
1496
1497                        if (bytes_read == byte_size)
1498                        {
1499                            switch (*f)
1500                            {
1501                            case 'd':
1502                            case 'i':
1503                            case 'o':
1504                            case 'u':
1505                            case 'X':
1506                            case 'x':
1507                            case 'a':
1508                            case 'A':
1509                            case 'f':
1510                            case 'F':
1511                            case 'e':
1512                            case 'E':
1513                            case 'g':
1514                            case 'G':
1515                            case 'p':
1516                            case 'c':
1517                            case 'C':
1518                                {
1519                                    if (is_register)
1520                                        data.SetData(&register_value.value.v_uint8[0], register_value.info.size);
1521                                    else
1522                                        data.SetData(&buf[0], bytes_read);
1523                                    DNBDataRef::offset_t data_offset = 0;
1524                                    if (byte_size <= 4)
1525                                    {
1526                                        uint32_t u32 = data.GetMax32(&data_offset, byte_size);
1527                                        // Show the actual byte width when displaying hex
1528                                        fprintf(file, fprintf_format.c_str(), u32);
1529                                    }
1530                                    else if (byte_size <= 8)
1531                                    {
1532                                        uint64_t u64 = data.GetMax64(&data_offset, byte_size);
1533                                        // Show the actual byte width when displaying hex
1534                                        fprintf(file, fprintf_format.c_str(), u64);
1535                                    }
1536                                    else
1537                                    {
1538                                        fprintf(file, "error: integer size not supported, must be 8 bytes or less (%u bytes).\n", byte_size);
1539                                    }
1540                                    if (!is_register)
1541                                        addr += byte_size;
1542                                }
1543                                break;
1544
1545                            case 's':
1546                                fprintf(file, fprintf_format.c_str(), buf.c_str());
1547                                addr += byte_size;
1548                                break;
1549
1550                            default:
1551                                fprintf(file, "error: unsupported conversion specifier '%c'.\n", *f);
1552                                break;
1553                            }
1554                        }
1555                    }
1556                }
1557                else
1558                    return total_bytes_read;
1559            }
1560            break;
1561
1562        case '\\':
1563            {
1564                f++;
1565                switch (*f)
1566                {
1567                case 'e': ch = '\e'; break;
1568                case 'a': ch = '\a'; break;
1569                case 'b': ch = '\b'; break;
1570                case 'f': ch = '\f'; break;
1571                case 'n': ch = '\n'; break;
1572                case 'r': ch = '\r'; break;
1573                case 't': ch = '\t'; break;
1574                case 'v': ch = '\v'; break;
1575                case '\'': ch = '\''; break;
1576                case '\\': ch = '\\'; break;
1577                case '0':
1578                case '1':
1579                case '2':
1580                case '3':
1581                case '4':
1582                case '5':
1583                case '6':
1584                case '7':
1585                    ch = strtoul(f, &end, 8);
1586                    f = end;
1587                    break;
1588                default:
1589                    ch = *f;
1590                    break;
1591                }
1592                fputc(ch, file);
1593            }
1594            break;
1595
1596        default:
1597            fputc(ch, file);
1598            break;
1599        }
1600    }
1601    return total_bytes_read;
1602}
1603
1604
1605//----------------------------------------------------------------------
1606// Get the number of threads for the specified process.
1607//----------------------------------------------------------------------
1608nub_size_t
1609DNBProcessGetNumThreads (nub_process_t pid)
1610{
1611    MachProcessSP procSP;
1612    if (GetProcessSP (pid, procSP))
1613        return procSP->GetNumThreads();
1614    return 0;
1615}
1616
1617//----------------------------------------------------------------------
1618// Get the thread ID of the current thread.
1619//----------------------------------------------------------------------
1620nub_thread_t
1621DNBProcessGetCurrentThread (nub_process_t pid)
1622{
1623    MachProcessSP procSP;
1624    if (GetProcessSP (pid, procSP))
1625        return procSP->GetCurrentThread();
1626    return 0;
1627}
1628
1629//----------------------------------------------------------------------
1630// Change the current thread.
1631//----------------------------------------------------------------------
1632nub_thread_t
1633DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid)
1634{
1635    MachProcessSP procSP;
1636    if (GetProcessSP (pid, procSP))
1637        return procSP->SetCurrentThread (tid);
1638    return INVALID_NUB_THREAD;
1639}
1640
1641
1642//----------------------------------------------------------------------
1643// Dump a string describing a thread's stop reason to the specified file
1644// handle
1645//----------------------------------------------------------------------
1646nub_bool_t
1647DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
1648{
1649    MachProcessSP procSP;
1650    if (GetProcessSP (pid, procSP))
1651        return procSP->GetThreadStoppedReason (tid, stop_info);
1652    return false;
1653}
1654
1655//----------------------------------------------------------------------
1656// Return string description for the specified thread.
1657//
1658// RETURNS: NULL if the thread isn't valid, else a NULL terminated C
1659// string from a static buffer that must be copied prior to subsequent
1660// calls.
1661//----------------------------------------------------------------------
1662const char *
1663DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid)
1664{
1665    MachProcessSP procSP;
1666    if (GetProcessSP (pid, procSP))
1667        return procSP->GetThreadInfo (tid);
1668    return NULL;
1669}
1670
1671//----------------------------------------------------------------------
1672// Get the thread ID given a thread index.
1673//----------------------------------------------------------------------
1674nub_thread_t
1675DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx)
1676{
1677    MachProcessSP procSP;
1678    if (GetProcessSP (pid, procSP))
1679        return procSP->GetThreadAtIndex (thread_idx);
1680    return INVALID_NUB_THREAD;
1681}
1682
1683nub_addr_t
1684DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid)
1685{
1686    MachProcessSP procSP;
1687    DNBError err;
1688    if (GetProcessSP (pid, procSP))
1689        return procSP->Task().GetDYLDAllImageInfosAddress (err);
1690    return INVALID_NUB_ADDRESS;
1691}
1692
1693
1694nub_bool_t
1695DNBProcessSharedLibrariesUpdated(nub_process_t pid)
1696{
1697    MachProcessSP procSP;
1698    if (GetProcessSP (pid, procSP))
1699    {
1700        procSP->SharedLibrariesUpdated ();
1701        return true;
1702    }
1703    return false;
1704}
1705
1706//----------------------------------------------------------------------
1707// Get the current shared library information for a process. Only return
1708// the shared libraries that have changed since the last shared library
1709// state changed event if only_changed is non-zero.
1710//----------------------------------------------------------------------
1711nub_size_t
1712DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos)
1713{
1714    MachProcessSP procSP;
1715    if (GetProcessSP (pid, procSP))
1716        return procSP->CopyImageInfos (image_infos, only_changed);
1717
1718    // If we have no process, then return NULL for the shared library info
1719    // and zero for shared library count
1720    *image_infos = NULL;
1721    return 0;
1722}
1723
1724//----------------------------------------------------------------------
1725// Get the register set information for a specific thread.
1726//----------------------------------------------------------------------
1727const DNBRegisterSetInfo *
1728DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
1729{
1730    return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
1731}
1732
1733
1734//----------------------------------------------------------------------
1735// Read a register value by register set and register index.
1736//----------------------------------------------------------------------
1737nub_bool_t
1738DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value)
1739{
1740    MachProcessSP procSP;
1741    ::bzero (value, sizeof(DNBRegisterValue));
1742    if (GetProcessSP (pid, procSP))
1743    {
1744        if (tid != INVALID_NUB_THREAD)
1745            return procSP->GetRegisterValue (tid, set, reg, value);
1746    }
1747    return false;
1748}
1749
1750nub_bool_t
1751DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value)
1752{
1753    if (tid != INVALID_NUB_THREAD)
1754    {
1755        MachProcessSP procSP;
1756        if (GetProcessSP (pid, procSP))
1757            return procSP->SetRegisterValue (tid, set, reg, value);
1758    }
1759    return false;
1760}
1761
1762nub_size_t
1763DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len)
1764{
1765    MachProcessSP procSP;
1766    if (GetProcessSP (pid, procSP))
1767    {
1768        if (tid != INVALID_NUB_THREAD)
1769            return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len);
1770    }
1771    ::bzero (buf, buf_len);
1772    return 0;
1773
1774}
1775
1776nub_size_t
1777DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len)
1778{
1779    MachProcessSP procSP;
1780    if (GetProcessSP (pid, procSP))
1781    {
1782        if (tid != INVALID_NUB_THREAD)
1783            return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len);
1784    }
1785    return 0;
1786}
1787
1788//----------------------------------------------------------------------
1789// Read a register value by name.
1790//----------------------------------------------------------------------
1791nub_bool_t
1792DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value)
1793{
1794    MachProcessSP procSP;
1795    ::bzero (value, sizeof(DNBRegisterValue));
1796    if (GetProcessSP (pid, procSP))
1797    {
1798        const struct DNBRegisterSetInfo *set_info;
1799        nub_size_t num_reg_sets = 0;
1800        set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1801        if (set_info)
1802        {
1803            uint32_t set = reg_set;
1804            uint32_t reg;
1805            if (set == REGISTER_SET_ALL)
1806            {
1807                for (set = 1; set < num_reg_sets; ++set)
1808                {
1809                    for (reg = 0; reg < set_info[set].num_registers; ++reg)
1810                    {
1811                        if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1812                            return procSP->GetRegisterValue (tid, set, reg, value);
1813                    }
1814                }
1815            }
1816            else
1817            {
1818                for (reg = 0; reg < set_info[set].num_registers; ++reg)
1819                {
1820                    if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1821                        return procSP->GetRegisterValue (tid, set, reg, value);
1822                }
1823            }
1824        }
1825    }
1826    return false;
1827}
1828
1829
1830//----------------------------------------------------------------------
1831// Read a register set and register number from the register name.
1832//----------------------------------------------------------------------
1833nub_bool_t
1834DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info)
1835{
1836    const struct DNBRegisterSetInfo *set_info;
1837    nub_size_t num_reg_sets = 0;
1838    set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1839    if (set_info)
1840    {
1841        uint32_t set, reg;
1842        for (set = 1; set < num_reg_sets; ++set)
1843        {
1844            for (reg = 0; reg < set_info[set].num_registers; ++reg)
1845            {
1846                if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1847                {
1848                    *info = set_info[set].registers[reg];
1849                    return true;
1850                }
1851            }
1852        }
1853
1854        for (set = 1; set < num_reg_sets; ++set)
1855        {
1856            uint32_t reg;
1857            for (reg = 0; reg < set_info[set].num_registers; ++reg)
1858            {
1859                if (set_info[set].registers[reg].alt == NULL)
1860                    continue;
1861
1862                if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0)
1863                {
1864                    *info = set_info[set].registers[reg];
1865                    return true;
1866                }
1867            }
1868        }
1869    }
1870
1871    ::bzero (info, sizeof(DNBRegisterInfo));
1872    return false;
1873}
1874
1875
1876//----------------------------------------------------------------------
1877// Set the name to address callback function that this nub can use
1878// for any name to address lookups that are needed.
1879//----------------------------------------------------------------------
1880nub_bool_t
1881DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton)
1882{
1883    MachProcessSP procSP;
1884    if (GetProcessSP (pid, procSP))
1885    {
1886        procSP->SetNameToAddressCallback (callback, baton);
1887        return true;
1888    }
1889    return false;
1890}
1891
1892
1893//----------------------------------------------------------------------
1894// Set the name to address callback function that this nub can use
1895// for any name to address lookups that are needed.
1896//----------------------------------------------------------------------
1897nub_bool_t
1898DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void  *baton)
1899{
1900    MachProcessSP procSP;
1901    if (GetProcessSP (pid, procSP))
1902    {
1903        procSP->SetSharedLibraryInfoCallback (callback, baton);
1904        return true;
1905    }
1906    return false;
1907}
1908
1909nub_addr_t
1910DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib)
1911{
1912    MachProcessSP procSP;
1913    if (GetProcessSP (pid, procSP))
1914    {
1915        return procSP->LookupSymbol (name, shlib);
1916    }
1917    return INVALID_NUB_ADDRESS;
1918}
1919
1920
1921nub_size_t
1922DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size)
1923{
1924    MachProcessSP procSP;
1925    if (GetProcessSP (pid, procSP))
1926        return procSP->GetAvailableSTDOUT (buf, buf_size);
1927    return 0;
1928}
1929
1930nub_size_t
1931DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size)
1932{
1933    MachProcessSP procSP;
1934    if (GetProcessSP (pid, procSP))
1935        return procSP->GetAvailableSTDERR (buf, buf_size);
1936    return 0;
1937}
1938
1939nub_size_t
1940DNBProcessGetStopCount (nub_process_t pid)
1941{
1942    MachProcessSP procSP;
1943    if (GetProcessSP (pid, procSP))
1944        return procSP->StopCount();
1945    return 0;
1946}
1947
1948nub_bool_t
1949DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
1950{
1951    if (path == NULL || path[0] == '\0')
1952        return false;
1953
1954    char max_path[PATH_MAX];
1955    std::string result;
1956    CFString::GlobPath(path, result);
1957
1958    if (result.empty())
1959        result = path;
1960
1961    if (realpath(path, max_path))
1962    {
1963        // Found the path relatively...
1964        ::strncpy(resolved_path, max_path, resolved_path_size);
1965        return strlen(resolved_path) + 1 < resolved_path_size;
1966    }
1967    else
1968    {
1969        // Not a relative path, check the PATH environment variable if the
1970        const char *PATH = getenv("PATH");
1971        if (PATH)
1972        {
1973            const char *curr_path_start = PATH;
1974            const char *curr_path_end;
1975            while (curr_path_start && *curr_path_start)
1976            {
1977                curr_path_end = strchr(curr_path_start, ':');
1978                if (curr_path_end == NULL)
1979                {
1980                    result.assign(curr_path_start);
1981                    curr_path_start = NULL;
1982                }
1983                else if (curr_path_end > curr_path_start)
1984                {
1985                    size_t len = curr_path_end - curr_path_start;
1986                    result.assign(curr_path_start, len);
1987                    curr_path_start += len + 1;
1988                }
1989                else
1990                    break;
1991
1992                result += '/';
1993                result += path;
1994                struct stat s;
1995                if (stat(result.c_str(), &s) == 0)
1996                {
1997                    ::strncpy(resolved_path, result.c_str(), resolved_path_size);
1998                    return result.size() + 1 < resolved_path_size;
1999                }
2000            }
2001        }
2002    }
2003    return false;
2004}
2005
2006
2007void
2008DNBInitialize()
2009{
2010    DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
2011#if defined (__i386__) || defined (__x86_64__)
2012    DNBArchImplI386::Initialize();
2013    DNBArchImplX86_64::Initialize();
2014#elif defined (__arm__)
2015    DNBArchMachARM::Initialize();
2016#endif
2017}
2018
2019void
2020DNBTerminate()
2021{
2022}
2023
2024nub_bool_t
2025DNBSetArchitecture (const char *arch)
2026{
2027    if (arch && arch[0])
2028    {
2029        if (strcasecmp (arch, "i386") == 0)
2030            return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386);
2031        else if (strcasecmp (arch, "x86_64") == 0)
2032            return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64);
2033        else if (strstr (arch, "arm") == arch)
2034            return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM);
2035    }
2036    return false;
2037}
2038