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