blob: 304c655921da7bff2aab9e55ea7da623585f2159 [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"
Jason Molenda1c739112013-02-22 07:27:08 +000015#include <inttypes.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include <signal.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/resource.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22#include <sys/wait.h>
23#include <unistd.h>
24#include <sys/sysctl.h>
25#include <map>
26#include <vector>
Jim Ingham490bccd2012-11-01 01:04:46 +000027#include <libproc.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028
Jason Molenda36a216e2014-07-24 01:36:24 +000029#if defined (__APPLE__)
30#include <pthread.h>
31#include <sched.h>
32#endif
33
Jason Molendaa3329782014-03-29 18:54:20 +000034#define TRY_KQUEUE 1
35
36#ifdef TRY_KQUEUE
37 #include <sys/event.h>
38 #include <sys/time.h>
39 #ifdef NOTE_EXIT_DETAIL
40 #define USE_KQUEUE
41 #endif
42#endif
43
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044#include "MacOSX/MachProcess.h"
45#include "MacOSX/MachTask.h"
Jason Molenda705b1802014-06-13 02:37:02 +000046#include "MacOSX/Genealogy.h"
47#include "MacOSX/ThreadInfo.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048#include "CFString.h"
49#include "DNBLog.h"
50#include "DNBDataRef.h"
51#include "DNBThreadResumeActions.h"
52#include "DNBTimer.h"
Greg Clayton48baf7a2012-10-31 21:44:39 +000053#include "CFBundle.h"
54
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055
Greg Clayton7b0992d2013-04-18 22:45:39 +000056typedef std::shared_ptr<MachProcess> MachProcessSP;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057typedef std::map<nub_process_t, MachProcessSP> ProcessMap;
58typedef ProcessMap::iterator ProcessMapIter;
59typedef ProcessMap::const_iterator ProcessMapConstIter;
60
Greg Clayton9eb4e032012-11-06 23:36:26 +000061size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos);
62static size_t GetAllInfosMatchingName (const char *process_name, std::vector<struct kinfo_proc>& matching_proc_infos);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000063
64//----------------------------------------------------------------------
65// A Thread safe singleton to get a process map pointer.
66//
67// Returns a pointer to the existing process map, or a pointer to a
68// newly created process map if CAN_CREATE is non-zero.
69//----------------------------------------------------------------------
70static ProcessMap*
71GetProcessMap(bool can_create)
72{
73 static ProcessMap* g_process_map_ptr = NULL;
74
75 if (can_create && g_process_map_ptr == NULL)
76 {
77 static pthread_mutex_t g_process_map_mutex = PTHREAD_MUTEX_INITIALIZER;
78 PTHREAD_MUTEX_LOCKER (locker, &g_process_map_mutex);
79 if (g_process_map_ptr == NULL)
80 g_process_map_ptr = new ProcessMap;
81 }
82 return g_process_map_ptr;
83}
84
85//----------------------------------------------------------------------
86// Add PID to the shared process pointer map.
87//
88// Return non-zero value if we succeed in adding the process to the map.
89// The only time this should fail is if we run out of memory and can't
90// allocate a ProcessMap.
91//----------------------------------------------------------------------
92static nub_bool_t
93AddProcessToMap (nub_process_t pid, MachProcessSP& procSP)
94{
95 ProcessMap* process_map = GetProcessMap(true);
96 if (process_map)
97 {
98 process_map->insert(std::make_pair(pid, procSP));
99 return true;
100 }
101 return false;
102}
103
104//----------------------------------------------------------------------
105// Remove the shared pointer for PID from the process map.
106//
107// Returns the number of items removed from the process map.
108//----------------------------------------------------------------------
109static size_t
110RemoveProcessFromMap (nub_process_t pid)
111{
112 ProcessMap* process_map = GetProcessMap(false);
113 if (process_map)
114 {
115 return process_map->erase(pid);
116 }
117 return 0;
118}
119
120//----------------------------------------------------------------------
121// Get the shared pointer for PID from the existing process map.
122//
123// Returns true if we successfully find a shared pointer to a
124// MachProcess object.
125//----------------------------------------------------------------------
126static nub_bool_t
127GetProcessSP (nub_process_t pid, MachProcessSP& procSP)
128{
129 ProcessMap* process_map = GetProcessMap(false);
130 if (process_map != NULL)
131 {
132 ProcessMapIter pos = process_map->find(pid);
133 if (pos != process_map->end())
134 {
135 procSP = pos->second;
136 return true;
137 }
138 }
139 procSP.reset();
140 return false;
141}
142
Jason Molendaa3329782014-03-29 18:54:20 +0000143#ifdef USE_KQUEUE
144void *
145kqueue_thread (void *arg)
146{
147 int kq_id = (int) (intptr_t) arg;
148
Jason Molenda36a216e2014-07-24 01:36:24 +0000149#if defined (__APPLE__)
150 pthread_setname_np ("kqueue thread");
151#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
152 struct sched_param thread_param;
153 int thread_sched_policy;
154 if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0)
155 {
156 thread_param.sched_priority = 47;
157 pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
158 }
159#endif
160#endif
161
Jason Molendaa3329782014-03-29 18:54:20 +0000162 struct kevent death_event;
163 while (1)
164 {
165 int n_events = kevent (kq_id, NULL, 0, &death_event, 1, NULL);
166 if (n_events == -1)
167 {
168 if (errno == EINTR)
169 continue;
170 else
171 {
172 DNBLogError ("kqueue failed with error: (%d): %s", errno, strerror(errno));
173 return NULL;
174 }
175 }
176 else if (death_event.flags & EV_ERROR)
177 {
178 int error_no = death_event.data;
179 const char *error_str = strerror(death_event.data);
180 if (error_str == NULL)
181 error_str = "Unknown error";
182 DNBLogError ("Failed to initialize kqueue event: (%d): %s", error_no, error_str );
183 return NULL;
184 }
185 else
186 {
187 int status;
Greg Clayton040c5602014-04-30 20:24:10 +0000188 const pid_t pid = (pid_t)death_event.ident;
189 const pid_t child_pid = waitpid (pid, &status, 0);
Jason Molendaa3329782014-03-29 18:54:20 +0000190
Greg Clayton040c5602014-04-30 20:24:10 +0000191
192 bool exited = false;
193 int signal = 0;
194 int exit_status = 0;
195 const char *status_cstr = NULL;
196 if (WIFSTOPPED(status))
197 {
198 signal = WSTOPSIG(status);
199 status_cstr = "STOPPED";
200 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)", child_pid, signal);
201 }
202 else if (WIFEXITED(status))
203 {
204 exit_status = WEXITSTATUS(status);
205 status_cstr = "EXITED";
206 exited = true;
207 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)", child_pid, exit_status);
208 }
209 else if (WIFSIGNALED(status))
210 {
211 signal = WTERMSIG(status);
212 status_cstr = "SIGNALED";
213 if (child_pid == abs(pid))
214 {
215 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED and EXITED (signal = %i)", child_pid, signal);
216 char exit_info[64];
217 ::snprintf (exit_info, sizeof(exit_info), "Terminated due to signal %i", signal);
218 DNBProcessSetExitInfo (child_pid, exit_info);
219 exited = true;
220 exit_status = INT8_MAX;
221 }
222 else
223 {
224 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED (signal = %i)", child_pid, signal);
225 }
226 }
227
228 if (exited)
229 {
230 if (death_event.data & NOTE_EXIT_MEMORY)
Jim Ingham0c7ebe92014-06-17 21:02:44 +0000231 DNBProcessSetExitInfo (child_pid, "Terminated due to memory issue");
Greg Clayton040c5602014-04-30 20:24:10 +0000232 else if (death_event.data & NOTE_EXIT_DECRYPTFAIL)
233 DNBProcessSetExitInfo (child_pid, "Terminated due to decrypt failure");
234 else if (death_event.data & NOTE_EXIT_CSERROR)
235 DNBProcessSetExitInfo (child_pid, "Terminated due to code signing error");
236
237 DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, exit_status);
238 DNBProcessSetExitStatus (child_pid, status);
239 return NULL;
240 }
Jason Molendaa3329782014-03-29 18:54:20 +0000241 }
242 }
243}
244
245static bool
246spawn_kqueue_thread (pid_t pid)
247{
248 pthread_t thread;
249 int kq_id;
250
251 kq_id = kqueue();
252 if (kq_id == -1)
253 {
254 DNBLogError ("Could not get kqueue for pid = %i.", pid);
255 return false;
256 }
257
258 struct kevent reg_event;
259
Jim Ingham60089242014-06-24 21:51:42 +0000260 EV_SET(&reg_event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT|NOTE_EXITSTATUS|NOTE_EXIT_DETAIL, 0, NULL);
Jason Molendaa3329782014-03-29 18:54:20 +0000261 // Register the event:
262 int result = kevent (kq_id, &reg_event, 1, NULL, 0, NULL);
263 if (result != 0)
264 {
265 DNBLogError ("Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, result);
266 return false;
267 }
268
269 int ret = ::pthread_create (&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id);
270
271 // pthread_create returns 0 if successful
272 if (ret == 0)
273 {
274 ::pthread_detach (thread);
275 return true;
276 }
277 return false;
278}
279#endif // #if USE_KQUEUE
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000280
281static void *
282waitpid_thread (void *arg)
283{
284 const pid_t pid = (pid_t)(intptr_t)arg;
285 int status;
Jason Molenda36a216e2014-07-24 01:36:24 +0000286
287#if defined (__APPLE__)
288 pthread_setname_np ("waitpid thread");
289#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
290 struct sched_param thread_param;
291 int thread_sched_policy;
292 if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0)
293 {
294 thread_param.sched_priority = 47;
295 pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
296 }
297#endif
298#endif
299
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000300 while (1)
301 {
302 pid_t child_pid = waitpid(pid, &status, 0);
Greg Clayton6467ff92013-06-27 00:23:57 +0000303 DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): waitpid (pid = %i, &status, 0) => %i, status = %i, errno = %i", pid, child_pid, status, errno);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000304
305 if (child_pid < 0)
306 {
307 if (errno == EINTR)
308 continue;
309 break;
310 }
311 else
312 {
313 if (WIFSTOPPED(status))
314 {
315 continue;
316 }
317 else// if (WIFEXITED(status) || WIFSIGNALED(status))
318 {
Greg Clayton6467ff92013-06-27 00:23:57 +0000319 DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): setting exit status for pid = %i to %i", child_pid, status);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000320 DNBProcessSetExitStatus (child_pid, status);
321 return NULL;
322 }
323 }
324 }
325
326 // We should never exit as long as our child process is alive, so if we
327 // do something else went wrong and we should exit...
Greg Clayton6467ff92013-06-27 00:23:57 +0000328 DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): main loop exited, setting exit status to an invalid value (-1) for pid %i", pid);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000329 DNBProcessSetExitStatus (pid, -1);
330 return NULL;
331}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000332static bool
333spawn_waitpid_thread (pid_t pid)
334{
Jason Molendaa3329782014-03-29 18:54:20 +0000335#ifdef USE_KQUEUE
336 bool success = spawn_kqueue_thread (pid);
337 if (success)
338 return true;
339#endif
340
Jason Molenda27148b32013-10-05 02:52:22 +0000341 pthread_t thread;
342 int ret = ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid);
343 // pthread_create returns 0 if successful
344 if (ret == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000345 {
346 ::pthread_detach (thread);
347 return true;
348 }
349 return false;
350}
351
352nub_process_t
353DNBProcessLaunch (const char *path,
354 char const *argv[],
355 const char *envp[],
Bruce Mitcheneraaa0ba32014-07-08 18:05:41 +0000356 const char *working_directory, // NULL => don't change, non-NULL => set working directory for inferior to this
Greg Clayton6779606a2011-01-22 23:43:18 +0000357 const char *stdin_path,
358 const char *stdout_path,
359 const char *stderr_path,
Caroline Ticef8da8632010-12-03 18:46:09 +0000360 bool no_stdio,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000361 nub_launch_flavor_t launch_flavor,
Greg Claytonf681b942010-08-31 18:35:14 +0000362 int disable_aslr,
Jason Molendaa3329782014-03-29 18:54:20 +0000363 const char *event_data,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000364 char *err_str,
365 size_t err_len)
366{
Greg Clayton43e0af02012-09-18 18:04:04 +0000367 DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, working_dir=%s, stdin=%s, stdout=%s, stderr=%s, no-stdio=%i, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = %llu) called...",
Greg Claytonbd82a5d2011-01-23 05:56:20 +0000368 __FUNCTION__,
369 path,
370 argv,
371 envp,
372 working_directory,
373 stdin_path,
374 stdout_path,
375 stderr_path,
376 no_stdio,
377 launch_flavor,
378 disable_aslr,
379 err_str,
Greg Clayton43e0af02012-09-18 18:04:04 +0000380 (uint64_t)err_len);
Greg Claytonbd82a5d2011-01-23 05:56:20 +0000381
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000382 if (err_str && err_len > 0)
383 err_str[0] = '\0';
384 struct stat path_stat;
385 if (::stat(path, &path_stat) == -1)
386 {
387 char stat_error[256];
388 ::strerror_r (errno, stat_error, sizeof(stat_error));
389 snprintf(err_str, err_len, "%s (%s)", stat_error, path);
390 return INVALID_NUB_PROCESS;
391 }
392
393 MachProcessSP processSP (new MachProcess);
394 if (processSP.get())
395 {
396 DNBError launch_err;
Greg Clayton6779606a2011-01-22 23:43:18 +0000397 pid_t pid = processSP->LaunchForDebug (path,
398 argv,
399 envp,
400 working_directory,
401 stdin_path,
402 stdout_path,
403 stderr_path,
404 no_stdio,
405 launch_flavor,
Jason Molendaa3329782014-03-29 18:54:20 +0000406 disable_aslr,
407 event_data,
Greg Clayton6779606a2011-01-22 23:43:18 +0000408 launch_err);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000409 if (err_str)
410 {
411 *err_str = '\0';
412 if (launch_err.Fail())
413 {
414 const char *launch_err_str = launch_err.AsString();
415 if (launch_err_str)
416 {
417 strncpy(err_str, launch_err_str, err_len-1);
418 err_str[err_len-1] = '\0'; // Make sure the error string is terminated
419 }
420 }
421 }
422
423 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
424
425 if (pid != INVALID_NUB_PROCESS)
426 {
427 // Spawn a thread to reap our child inferior process...
428 spawn_waitpid_thread (pid);
429
430 if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL)
431 {
432 // We failed to get the task for our process ID which is bad.
Greg Claytonfb640c22012-02-02 19:23:22 +0000433 // Kill our process otherwise it will be stopped at the entry
434 // point and get reparented to someone else and never go away.
Jason Molenda153c8e02013-01-05 06:08:51 +0000435 DNBLog ("Could not get task port for process, sending SIGKILL and exiting.");
Greg Claytonfb640c22012-02-02 19:23:22 +0000436 kill (SIGKILL, pid);
437
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000438 if (err_str && err_len > 0)
439 {
440 if (launch_err.AsString())
441 {
442 ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString());
443 }
444 else
445 {
446 ::snprintf (err_str, err_len, "failed to get the task for process %i", pid);
447 }
448 }
449 }
450 else
451 {
Charles Davisb786e7d2012-02-21 00:53:12 +0000452 bool res = AddProcessToMap(pid, processSP);
453 assert(res && "Couldn't add process to map!");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000454 return pid;
455 }
456 }
457 }
458 return INVALID_NUB_PROCESS;
459}
460
461nub_process_t
462DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
463{
464 if (err_str && err_len > 0)
465 err_str[0] = '\0';
466 std::vector<struct kinfo_proc> matching_proc_infos;
467 size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
468 if (num_matching_proc_infos == 0)
469 {
470 DNBLogError ("error: no processes match '%s'\n", name);
471 return INVALID_NUB_PROCESS;
472 }
473 else if (num_matching_proc_infos > 1)
474 {
Greg Clayton43e0af02012-09-18 18:04:04 +0000475 DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000476 size_t i;
477 for (i=0; i<num_matching_proc_infos; ++i)
478 DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
479 return INVALID_NUB_PROCESS;
480 }
Greg Clayton3af9ea52010-11-18 05:57:03 +0000481
482 return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000483}
484
485nub_process_t
486DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len)
487{
488 if (err_str && err_len > 0)
489 err_str[0] = '\0';
490
Johnny Chen64503c82011-08-11 19:03:44 +0000491 pid_t pid = INVALID_NUB_PROCESS;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000492 MachProcessSP processSP(new MachProcess);
493 if (processSP.get())
494 {
495 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid);
496 pid = processSP->AttachForDebug (attach_pid, err_str, err_len);
497
498 if (pid != INVALID_NUB_PROCESS)
499 {
Charles Davisb786e7d2012-02-21 00:53:12 +0000500 bool res = AddProcessToMap(pid, processSP);
501 assert(res && "Couldn't add process to map!");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000502 spawn_waitpid_thread(pid);
503 }
504 }
505
506 while (pid != INVALID_NUB_PROCESS)
507 {
508 // Wait for process to start up and hit entry point
Greg Clayton3af9ea52010-11-18 05:57:03 +0000509 DNBLogThreadedIf (LOG_PROCESS,
510 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
511 __FUNCTION__,
512 pid);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000513 nub_event_t set_events = DNBProcessWaitForEvents (pid,
Greg Clayton3af9ea52010-11-18 05:57:03 +0000514 eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
515 true,
516 timeout);
517
518 DNBLogThreadedIf (LOG_PROCESS,
519 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
520 __FUNCTION__,
521 pid,
522 set_events);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000523
524 if (set_events == 0)
525 {
526 if (err_str && err_len > 0)
527 snprintf(err_str, err_len, "operation timed out");
528 pid = INVALID_NUB_PROCESS;
529 }
530 else
531 {
532 if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
533 {
534 nub_state_t pid_state = DNBProcessGetState (pid);
535 DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s",
536 __FUNCTION__, pid, DNBStateAsString(pid_state));
537
538 switch (pid_state)
539 {
Greg Clayton3af9ea52010-11-18 05:57:03 +0000540 default:
541 case eStateInvalid:
542 case eStateUnloaded:
543 case eStateAttaching:
544 case eStateLaunching:
545 case eStateSuspended:
546 break; // Ignore
547
548 case eStateRunning:
549 case eStateStepping:
550 // Still waiting to stop at entry point...
551 break;
552
553 case eStateStopped:
554 case eStateCrashed:
555 return pid;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000556
Greg Clayton3af9ea52010-11-18 05:57:03 +0000557 case eStateDetached:
558 case eStateExited:
559 if (err_str && err_len > 0)
560 snprintf(err_str, err_len, "process exited");
561 return INVALID_NUB_PROCESS;
562 }
563 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000564
565 DNBProcessResetEvents(pid, set_events);
566 }
567 }
568
569 return INVALID_NUB_PROCESS;
570}
571
Greg Clayton9eb4e032012-11-06 23:36:26 +0000572size_t
Greg Clayton3af9ea52010-11-18 05:57:03 +0000573GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000574{
Greg Clayton9eb4e032012-11-06 23:36:26 +0000575 size_t size = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000576 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
Jim Inghamc1fdb882014-06-27 16:02:55 +0000577 u_int namelen = sizeof(name)/sizeof(int);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000578 int err;
579
580 // Try to find out how many processes are around so we can
581 // size the buffer appropriately. sysctl's man page specifically suggests
582 // this approach, and says it returns a bit larger size than needed to
583 // handle any new processes created between then and now.
584
585 err = ::sysctl (name, namelen, NULL, &size, NULL, 0);
586
587 if ((err < 0) && (err != ENOMEM))
588 {
589 proc_infos.clear();
590 perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
591 return 0;
592 }
593
594
595 // Increase the size of the buffer by a few processes in case more have
596 // been spawned
597 proc_infos.resize (size / sizeof(struct kinfo_proc));
598 size = proc_infos.size() * sizeof(struct kinfo_proc); // Make sure we don't exceed our resize...
599 err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0);
600 if (err < 0)
601 {
602 proc_infos.clear();
603 return 0;
604 }
605
606 // Trim down our array to fit what we actually got back
607 proc_infos.resize(size / sizeof(struct kinfo_proc));
608 return proc_infos.size();
609}
610
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000611static size_t
612GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos)
613{
614
615 matching_proc_infos.clear();
616 if (full_process_name && full_process_name[0])
617 {
618 // We only get the process name, not the full path, from the proc_info. So just take the
619 // base name of the process name...
620 const char *process_name;
621 process_name = strrchr (full_process_name, '/');
622 if (process_name == NULL)
Greg Clayton7dab2be2012-07-19 02:45:35 +0000623 process_name = full_process_name;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000624 else
Greg Clayton7dab2be2012-07-19 02:45:35 +0000625 process_name++;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000626
Greg Clayton7dab2be2012-07-19 02:45:35 +0000627 const int process_name_len = strlen(process_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000628 std::vector<struct kinfo_proc> proc_infos;
629 const size_t num_proc_infos = GetAllInfos(proc_infos);
630 if (num_proc_infos > 0)
631 {
632 uint32_t i;
633 for (i=0; i<num_proc_infos; i++)
634 {
635 // Skip zombie processes and processes with unset status
636 if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB)
637 continue;
638
639 // Check for process by name. We only check the first MAXCOMLEN
640 // chars as that is all that kp_proc.p_comm holds.
Jim Ingham490bccd2012-11-01 01:04:46 +0000641
Greg Clayton7dab2be2012-07-19 02:45:35 +0000642 if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000643 {
Greg Clayton7dab2be2012-07-19 02:45:35 +0000644 if (process_name_len > MAXCOMLEN)
645 {
646 // We found a matching process name whose first MAXCOMLEN
647 // characters match, but there is more to the name than
Jim Ingham490bccd2012-11-01 01:04:46 +0000648 // this. We need to get the full process name. Use proc_pidpath, which will get
649 // us the full path to the executed process.
Greg Clayton7dab2be2012-07-19 02:45:35 +0000650
Jim Ingham490bccd2012-11-01 01:04:46 +0000651 char proc_path_buf[PATH_MAX];
Greg Clayton7dab2be2012-07-19 02:45:35 +0000652
Jim Ingham490bccd2012-11-01 01:04:46 +0000653 int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX);
654 if (return_val > 0)
Greg Clayton7dab2be2012-07-19 02:45:35 +0000655 {
Jim Ingham490bccd2012-11-01 01:04:46 +0000656 // Okay, now search backwards from that to see if there is a
657 // slash in the name. Note, even though we got all the args we don't care
658 // because the list data is just a bunch of concatenated null terminated strings
659 // so strrchr will start from the end of argv0.
660
661 const char *argv_basename = strrchr(proc_path_buf, '/');
Greg Clayton7dab2be2012-07-19 02:45:35 +0000662 if (argv_basename)
663 {
664 // Skip the '/'
665 ++argv_basename;
666 }
667 else
668 {
669 // We didn't find a directory delimiter in the process argv[0], just use what was in there
Jim Ingham490bccd2012-11-01 01:04:46 +0000670 argv_basename = proc_path_buf;
Greg Clayton7dab2be2012-07-19 02:45:35 +0000671 }
672
673 if (argv_basename)
674 {
675 if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0)
676 {
677 matching_proc_infos.push_back(proc_infos[i]);
678 }
679 }
680 }
681 }
682 else
683 {
684 // We found a matching process, add it to our list
Greg Clayton7dab2be2012-07-19 02:45:35 +0000685 matching_proc_infos.push_back(proc_infos[i]);
686 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000687 }
688 }
689 }
690 }
691 // return the newly added matches.
692 return matching_proc_infos.size();
693}
694
695nub_process_t
Greg Clayton19388cf2010-10-18 01:45:30 +0000696DNBProcessAttachWait (const char *waitfor_process_name,
697 nub_launch_flavor_t launch_flavor,
Jim Inghamcd16df92012-07-20 21:37:13 +0000698 bool ignore_existing,
Greg Clayton19388cf2010-10-18 01:45:30 +0000699 struct timespec *timeout_abstime,
700 useconds_t waitfor_interval,
701 char *err_str,
702 size_t err_len,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000703 DNBShouldCancelCallback should_cancel_callback,
704 void *callback_data)
705{
706 DNBError prepare_error;
707 std::vector<struct kinfo_proc> exclude_proc_infos;
708 size_t num_exclude_proc_infos;
709
710 // If the PrepareForAttach returns a valid token, use MachProcess to check
711 // for the process, otherwise scan the process table.
712
713 const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error);
714
715 if (prepare_error.Fail())
716 {
717 DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString());
718 return INVALID_NUB_PROCESS;
719 }
720
721 if (attach_token == NULL)
Jim Inghamcd16df92012-07-20 21:37:13 +0000722 {
723 if (ignore_existing)
724 num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
725 else
726 num_exclude_proc_infos = 0;
727 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000728
729 DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
730
731 // Loop and try to find the process by name
732 nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
733
734 while (waitfor_pid == INVALID_NUB_PROCESS)
735 {
736 if (attach_token != NULL)
737 {
738 nub_process_t pid;
739 pid = MachProcess::CheckForProcess(attach_token);
740 if (pid != INVALID_NUB_PROCESS)
741 {
742 waitfor_pid = pid;
743 break;
744 }
745 }
746 else
747 {
748
749 // Get the current process list, and check for matches that
750 // aren't in our original list. If anyone wants to attach
751 // to an existing process by name, they should do it with
752 // --attach=PROCNAME. Else we will wait for the first matching
753 // process that wasn't in our exclusion list.
754 std::vector<struct kinfo_proc> proc_infos;
755 const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos);
756 for (size_t i=0; i<num_proc_infos; i++)
757 {
758 nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
759 for (size_t j=0; j<num_exclude_proc_infos; j++)
760 {
761 if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid)
762 {
763 // This process was in our exclusion list, don't use it.
764 curr_pid = INVALID_NUB_PROCESS;
765 break;
766 }
767 }
768
769 // If we didn't find CURR_PID in our exclusion list, then use it.
770 if (curr_pid != INVALID_NUB_PROCESS)
771 {
772 // We found our process!
773 waitfor_pid = curr_pid;
774 break;
775 }
776 }
777 }
778
779 // If we haven't found our process yet, check for a timeout
780 // and then sleep for a bit until we poll again.
781 if (waitfor_pid == INVALID_NUB_PROCESS)
782 {
783 if (timeout_abstime != NULL)
784 {
785 // Check to see if we have a waitfor-duration option that
786 // has timed out?
787 if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime))
788 {
789 if (err_str && err_len > 0)
790 snprintf(err_str, err_len, "operation timed out");
791 DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name);
792 return INVALID_NUB_PROCESS;
793 }
794 }
795
796 // Call the should cancel callback as well...
797
798 if (should_cancel_callback != NULL
799 && should_cancel_callback (callback_data))
800 {
801 DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback.");
802 waitfor_pid = INVALID_NUB_PROCESS;
803 break;
804 }
805
806 ::usleep (waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again
807 }
808 }
809
810 if (waitfor_pid != INVALID_NUB_PROCESS)
811 {
812 DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid);
813 waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len);
814 }
815
816 bool success = waitfor_pid != INVALID_NUB_PROCESS;
817 MachProcess::CleanupAfterAttach (attach_token, success, prepare_error);
818
819 return waitfor_pid;
820}
821
822nub_bool_t
823DNBProcessDetach (nub_process_t pid)
824{
825 MachProcessSP procSP;
826 if (GetProcessSP (pid, procSP))
827 {
Jim Ingham58813182014-02-25 04:53:13 +0000828 const bool remove = true;
829 DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid);
830 procSP->DisableAllBreakpoints(remove);
831 procSP->DisableAllWatchpoints (remove);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000832 return procSP->Detach();
833 }
834 return false;
835}
836
837nub_bool_t
838DNBProcessKill (nub_process_t pid)
839{
840 MachProcessSP procSP;
841 if (GetProcessSP (pid, procSP))
842 {
843 return procSP->Kill ();
844 }
845 return false;
846}
847
848nub_bool_t
849DNBProcessSignal (nub_process_t pid, int signal)
850{
851 MachProcessSP procSP;
852 if (GetProcessSP (pid, procSP))
853 {
854 return procSP->Signal (signal);
855 }
856 return false;
857}
858
Greg Clayton4296c222014-04-24 19:54:32 +0000859
860nub_bool_t
861DNBProcessInterrupt(nub_process_t pid)
862{
863 MachProcessSP procSP;
864 if (GetProcessSP (pid, procSP))
865 return procSP->Interrupt();
866 return false;
867}
868
Jason Molendaa3329782014-03-29 18:54:20 +0000869nub_bool_t
870DNBProcessSendEvent (nub_process_t pid, const char *event)
871{
872 MachProcessSP procSP;
873 if (GetProcessSP (pid, procSP))
874 {
875 // FIXME: Do something with the error...
876 DNBError send_error;
877 return procSP->SendEvent (event, send_error);
878 }
879 return false;
880}
881
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000882
883nub_bool_t
884DNBProcessIsAlive (nub_process_t pid)
885{
886 MachProcessSP procSP;
887 if (GetProcessSP (pid, procSP))
888 {
889 return MachTask::IsValid (procSP->Task().TaskPort());
890 }
891 return eStateInvalid;
892}
893
894//----------------------------------------------------------------------
895// Process and Thread state information
896//----------------------------------------------------------------------
897nub_state_t
898DNBProcessGetState (nub_process_t pid)
899{
900 MachProcessSP procSP;
901 if (GetProcessSP (pid, procSP))
902 {
903 return procSP->GetState();
904 }
905 return eStateInvalid;
906}
907
908//----------------------------------------------------------------------
909// Process and Thread state information
910//----------------------------------------------------------------------
911nub_bool_t
912DNBProcessGetExitStatus (nub_process_t pid, int* status)
913{
914 MachProcessSP procSP;
915 if (GetProcessSP (pid, procSP))
916 {
917 return procSP->GetExitStatus(status);
918 }
919 return false;
920}
921
922nub_bool_t
923DNBProcessSetExitStatus (nub_process_t pid, int status)
924{
925 MachProcessSP procSP;
926 if (GetProcessSP (pid, procSP))
927 {
928 procSP->SetExitStatus(status);
929 return true;
930 }
931 return false;
932}
933
Jason Molendaa3329782014-03-29 18:54:20 +0000934const char *
935DNBProcessGetExitInfo (nub_process_t pid)
936{
937 MachProcessSP procSP;
938 if (GetProcessSP (pid, procSP))
939 {
940 return procSP->GetExitInfo();
941 }
942 return NULL;
943}
944
945nub_bool_t
946DNBProcessSetExitInfo (nub_process_t pid, const char *info)
947{
948 MachProcessSP procSP;
949 if (GetProcessSP (pid, procSP))
950 {
951 procSP->SetExitInfo(info);
952 return true;
953 }
954 return false;
955}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000956
957const char *
958DNBThreadGetName (nub_process_t pid, nub_thread_t tid)
959{
960 MachProcessSP procSP;
961 if (GetProcessSP (pid, procSP))
962 return procSP->ThreadGetName(tid);
963 return NULL;
964}
965
966
967nub_bool_t
968DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info)
969{
970 MachProcessSP procSP;
971 if (GetProcessSP (pid, procSP))
972 return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
973 return false;
974}
975
976nub_state_t
977DNBThreadGetState (nub_process_t pid, nub_thread_t tid)
978{
979 MachProcessSP procSP;
980 if (GetProcessSP (pid, procSP))
981 {
982 return procSP->ThreadGetState(tid);
983 }
984 return eStateInvalid;
985}
986
987const char *
988DNBStateAsString(nub_state_t state)
989{
990 switch (state)
991 {
Greg Claytoneffe5c92011-05-03 22:09:39 +0000992 case eStateInvalid: return "Invalid";
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000993 case eStateUnloaded: return "Unloaded";
994 case eStateAttaching: return "Attaching";
995 case eStateLaunching: return "Launching";
996 case eStateStopped: return "Stopped";
997 case eStateRunning: return "Running";
998 case eStateStepping: return "Stepping";
999 case eStateCrashed: return "Crashed";
1000 case eStateDetached: return "Detached";
1001 case eStateExited: return "Exited";
1002 case eStateSuspended: return "Suspended";
1003 }
1004 return "nub_state_t ???";
1005}
1006
Jason Molenda705b1802014-06-13 02:37:02 +00001007Genealogy::ThreadActivitySP
1008DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out)
1009{
1010 Genealogy::ThreadActivitySP thread_activity_sp;
1011 MachProcessSP procSP;
1012 if (GetProcessSP (pid, procSP))
1013 thread_activity_sp = procSP->GetGenealogyInfoForThread (tid, timed_out);
1014 return thread_activity_sp;
1015}
1016
1017Genealogy::ProcessExecutableInfoSP
1018DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx)
1019{
1020 Genealogy::ProcessExecutableInfoSP image_info_sp;
1021 MachProcessSP procSP;
1022 if (GetProcessSP (pid, procSP))
1023 {
1024 image_info_sp = procSP->GetGenealogyImageInfo (idx);
1025 }
1026 return image_info_sp;
1027}
1028
1029ThreadInfo::QoS
1030DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index)
1031{
1032 MachProcessSP procSP;
1033 if (GetProcessSP (pid, procSP))
1034 {
1035 return procSP->GetRequestedQoS (tid, tsd, dti_qos_class_index);
1036 }
1037 return ThreadInfo::QoS();
1038}
1039
1040nub_addr_t
1041DNBGetPThreadT (nub_process_t pid, nub_thread_t tid)
1042{
1043 MachProcessSP procSP;
1044 if (GetProcessSP (pid, procSP))
1045 {
1046 return procSP->GetPThreadT (tid);
1047 }
1048 return INVALID_NUB_ADDRESS;
1049}
1050
1051nub_addr_t
1052DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid)
1053{
1054 MachProcessSP procSP;
1055 if (GetProcessSP (pid, procSP))
1056 {
1057 return procSP->GetDispatchQueueT (tid);
1058 }
1059 return INVALID_NUB_ADDRESS;
1060}
1061
1062nub_addr_t
1063DNBGetTSDAddressForThread (nub_process_t pid, nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size)
1064{
1065 MachProcessSP procSP;
1066 if (GetProcessSP (pid, procSP))
1067 {
1068 return procSP->GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
1069 }
1070 return INVALID_NUB_ADDRESS;
1071}
1072
1073
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001074const char *
1075DNBProcessGetExecutablePath (nub_process_t pid)
1076{
1077 MachProcessSP procSP;
1078 if (GetProcessSP (pid, procSP))
1079 {
1080 return procSP->Path();
1081 }
1082 return NULL;
1083}
1084
1085nub_size_t
1086DNBProcessGetArgumentCount (nub_process_t pid)
1087{
1088 MachProcessSP procSP;
1089 if (GetProcessSP (pid, procSP))
1090 {
1091 return procSP->ArgumentCount();
1092 }
1093 return 0;
1094}
1095
1096const char *
1097DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx)
1098{
1099 MachProcessSP procSP;
1100 if (GetProcessSP (pid, procSP))
1101 {
1102 return procSP->ArgumentAtIndex (idx);
1103 }
1104 return NULL;
1105}
1106
1107
1108//----------------------------------------------------------------------
1109// Execution control
1110//----------------------------------------------------------------------
1111nub_bool_t
1112DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions)
1113{
1114 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1115 MachProcessSP procSP;
1116 if (GetProcessSP (pid, procSP))
1117 {
1118 DNBThreadResumeActions thread_actions (actions, num_actions);
1119
1120 // Below we add a default thread plan just in case one wasn't
1121 // provided so all threads always know what they were supposed to do
1122 if (thread_actions.IsEmpty())
1123 {
1124 // No thread plans were given, so the default it to run all threads
1125 thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
1126 }
1127 else
1128 {
1129 // Some thread plans were given which means anything that wasn't
1130 // specified should remain stopped.
1131 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
1132 }
1133 return procSP->Resume (thread_actions);
1134 }
1135 return false;
1136}
1137
1138nub_bool_t
1139DNBProcessHalt (nub_process_t pid)
1140{
1141 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1142 MachProcessSP procSP;
1143 if (GetProcessSP (pid, procSP))
1144 return procSP->Signal (SIGSTOP);
1145 return false;
1146}
1147//
1148//nub_bool_t
1149//DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
1150//{
1151// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step);
1152// MachProcessSP procSP;
1153// if (GetProcessSP (pid, procSP))
1154// {
1155// return procSP->Resume(tid, step, 0);
1156// }
1157// return false;
1158//}
1159//
1160//nub_bool_t
1161//DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal)
1162//{
1163// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
1164// MachProcessSP procSP;
1165// if (GetProcessSP (pid, procSP))
1166// {
1167// return procSP->Resume(tid, step, signal);
1168// }
1169// return false;
1170//}
1171
1172nub_event_t
1173DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout)
1174{
1175 nub_event_t result = 0;
1176 MachProcessSP procSP;
1177 if (GetProcessSP (pid, procSP))
1178 {
1179 if (wait_for_set)
1180 result = procSP->Events().WaitForSetEvents(event_mask, timeout);
1181 else
1182 result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
1183 }
1184 return result;
1185}
1186
1187void
1188DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask)
1189{
1190 MachProcessSP procSP;
1191 if (GetProcessSP (pid, procSP))
1192 procSP->Events().ResetEvents(event_mask);
1193}
1194
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001195// Breakpoints
Greg Claytond8cf1a12013-06-12 00:46:38 +00001196nub_bool_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001197DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
1198{
1199 MachProcessSP procSP;
1200 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001201 return procSP->CreateBreakpoint(addr, size, hardware) != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001202 return false;
1203}
1204
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001205nub_bool_t
Greg Claytond8cf1a12013-06-12 00:46:38 +00001206DNBBreakpointClear (nub_process_t pid, nub_addr_t addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001207{
1208 MachProcessSP procSP;
1209 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001210 return procSP->DisableBreakpoint(addr, true);
1211 return false; // Failed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001212}
1213
Greg Claytond8cf1a12013-06-12 00:46:38 +00001214
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001215//----------------------------------------------------------------------
1216// Watchpoints
1217//----------------------------------------------------------------------
Greg Claytond8cf1a12013-06-12 00:46:38 +00001218nub_bool_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001219DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware)
1220{
1221 MachProcessSP procSP;
1222 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001223 return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001224 return false;
1225}
1226
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001227nub_bool_t
Greg Claytond8cf1a12013-06-12 00:46:38 +00001228DNBWatchpointClear (nub_process_t pid, nub_addr_t addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001229{
1230 MachProcessSP procSP;
1231 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001232 return procSP->DisableWatchpoint(addr, true);
1233 return false; // Failed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001234}
1235
1236//----------------------------------------------------------------------
Johnny Chen64637202012-05-23 21:09:52 +00001237// Return the number of supported hardware watchpoints.
1238//----------------------------------------------------------------------
1239uint32_t
1240DNBWatchpointGetNumSupportedHWP (nub_process_t pid)
1241{
1242 MachProcessSP procSP;
1243 if (GetProcessSP (pid, procSP))
1244 return procSP->GetNumSupportedHardwareWatchpoints();
1245 return 0;
1246}
1247
1248//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001249// Read memory in the address space of process PID. This call will take
1250// care of setting and restoring permissions and breaking up the memory
1251// read into multiple chunks as required.
1252//
1253// RETURNS: number of bytes actually read
1254//----------------------------------------------------------------------
1255nub_size_t
1256DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf)
1257{
1258 MachProcessSP procSP;
1259 if (GetProcessSP (pid, procSP))
1260 return procSP->ReadMemory(addr, size, buf);
1261 return 0;
1262}
1263
1264//----------------------------------------------------------------------
1265// Write memory to the address space of process PID. This call will take
1266// care of setting and restoring permissions and breaking up the memory
1267// write into multiple chunks as required.
1268//
1269// RETURNS: number of bytes actually written
1270//----------------------------------------------------------------------
1271nub_size_t
1272DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf)
1273{
1274 MachProcessSP procSP;
1275 if (GetProcessSP (pid, procSP))
1276 return procSP->WriteMemory(addr, size, buf);
1277 return 0;
1278}
1279
1280nub_addr_t
1281DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions)
1282{
1283 MachProcessSP procSP;
1284 if (GetProcessSP (pid, procSP))
1285 return procSP->Task().AllocateMemory (size, permissions);
1286 return 0;
1287}
1288
1289nub_bool_t
1290DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr)
1291{
1292 MachProcessSP procSP;
1293 if (GetProcessSP (pid, procSP))
1294 return procSP->Task().DeallocateMemory (addr);
1295 return 0;
1296}
1297
Jason Molenda1f3966b2011-11-08 04:28:12 +00001298//----------------------------------------------------------------------
Jason Molenda3dc85832011-11-09 08:03:56 +00001299// Find attributes of the memory region that contains ADDR for process PID,
1300// if possible, and return a string describing those attributes.
Jason Molenda1f3966b2011-11-08 04:28:12 +00001301//
Jason Molenda3dc85832011-11-09 08:03:56 +00001302// Returns 1 if we could find attributes for this region and OUTBUF can
1303// be sent to the remote debugger.
Jason Molenda1f3966b2011-11-08 04:28:12 +00001304//
Jason Molenda3dc85832011-11-09 08:03:56 +00001305// Returns 0 if we couldn't find the attributes for a region of memory at
1306// that address and OUTBUF should not be sent.
1307//
1308// Returns -1 if this platform cannot look up information about memory regions
1309// or if we do not yet have a valid launched process.
1310//
Jason Molenda1f3966b2011-11-08 04:28:12 +00001311//----------------------------------------------------------------------
1312int
Greg Claytonfc5dd292011-12-12 18:51:14 +00001313DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info)
Jason Molenda1f3966b2011-11-08 04:28:12 +00001314{
1315 MachProcessSP procSP;
1316 if (GetProcessSP (pid, procSP))
Greg Clayton46fb5582011-11-18 07:03:08 +00001317 return procSP->Task().GetMemoryRegionInfo (addr, region_info);
1318
Jason Molenda1f3966b2011-11-08 04:28:12 +00001319 return -1;
1320}
1321
Han Ming Ong929a94f2012-11-29 22:14:45 +00001322std::string
Han Ming Ong8764fe72013-03-04 21:25:51 +00001323DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType)
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001324{
1325 MachProcessSP procSP;
1326 if (GetProcessSP (pid, procSP))
Han Ming Ong8764fe72013-03-04 21:25:51 +00001327 return procSP->Task().GetProfileData(scanType);
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001328
Han Ming Ong929a94f2012-11-29 22:14:45 +00001329 return std::string("");
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001330}
1331
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001332nub_bool_t
Han Ming Ong8764fe72013-03-04 21:25:51 +00001333DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001334{
1335 MachProcessSP procSP;
1336 if (GetProcessSP (pid, procSP))
1337 {
Han Ming Ong8764fe72013-03-04 21:25:51 +00001338 procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type);
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001339 return true;
1340 }
1341
1342 return false;
1343}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001344
1345//----------------------------------------------------------------------
1346// Formatted output that uses memory and registers from process and
1347// thread in place of arguments.
1348//----------------------------------------------------------------------
1349nub_size_t
1350DNBPrintf (nub_process_t pid, nub_thread_t tid, nub_addr_t base_addr, FILE *file, const char *format)
1351{
1352 if (file == NULL)
1353 return 0;
1354 enum printf_flags
1355 {
1356 alternate_form = (1 << 0),
1357 zero_padding = (1 << 1),
1358 negative_field_width = (1 << 2),
1359 blank_space = (1 << 3),
1360 show_sign = (1 << 4),
1361 show_thousands_separator= (1 << 5),
1362 };
1363
1364 enum printf_length_modifiers
1365 {
1366 length_mod_h = (1 << 0),
1367 length_mod_hh = (1 << 1),
1368 length_mod_l = (1 << 2),
1369 length_mod_ll = (1 << 3),
1370 length_mod_L = (1 << 4),
1371 length_mod_j = (1 << 5),
1372 length_mod_t = (1 << 6),
1373 length_mod_z = (1 << 7),
1374 length_mod_q = (1 << 8),
1375 };
1376
1377 nub_addr_t addr = base_addr;
1378 char *end_format = (char*)format + strlen(format);
1379 char *end = NULL; // For strtoXXXX calls;
1380 std::basic_string<uint8_t> buf;
1381 nub_size_t total_bytes_read = 0;
1382 DNBDataRef data;
1383 const char *f;
1384 for (f = format; *f != '\0' && f < end_format; f++)
1385 {
1386 char ch = *f;
1387 switch (ch)
1388 {
1389 case '%':
1390 {
1391 f++; // Skip the '%' character
Greg Clayton23f59502012-07-17 03:23:13 +00001392// int min_field_width = 0;
1393// int precision = 0;
1394 //uint32_t flags = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001395 uint32_t length_modifiers = 0;
1396 uint32_t byte_size = 0;
1397 uint32_t actual_byte_size = 0;
1398 bool is_string = false;
1399 bool is_register = false;
1400 DNBRegisterValue register_value;
1401 int64_t register_offset = 0;
1402 nub_addr_t register_addr = INVALID_NUB_ADDRESS;
1403
1404 // Create the format string to use for this conversion specification
1405 // so we can remove and mprintf specific flags and formatters.
1406 std::string fprintf_format("%");
1407
1408 // Decode any flags
1409 switch (*f)
1410 {
Greg Clayton23f59502012-07-17 03:23:13 +00001411 case '#': fprintf_format += *f++; break; //flags |= alternate_form; break;
1412 case '0': fprintf_format += *f++; break; //flags |= zero_padding; break;
1413 case '-': fprintf_format += *f++; break; //flags |= negative_field_width; break;
1414 case ' ': fprintf_format += *f++; break; //flags |= blank_space; break;
1415 case '+': fprintf_format += *f++; break; //flags |= show_sign; break;
1416 case ',': fprintf_format += *f++; break; //flags |= show_thousands_separator;break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001417 case '{':
1418 case '[':
1419 {
1420 // We have a register name specification that can take two forms:
1421 // ${regname} or ${regname+offset}
1422 // The action is to read the register value and add the signed offset
1423 // (if any) and use that as the value to format.
1424 // $[regname] or $[regname+offset]
1425 // The action is to read the register value and add the signed offset
1426 // (if any) and use the result as an address to dereference. The size
1427 // of what is dereferenced is specified by the actual byte size that
1428 // follows the minimum field width and precision (see comments below).
1429 switch (*f)
1430 {
1431 case '{':
1432 case '[':
1433 {
1434 char open_scope_ch = *f;
1435 f++;
1436 const char *reg_name = f;
1437 size_t reg_name_length = strcspn(f, "+-}]");
1438 if (reg_name_length > 0)
1439 {
1440 std::string register_name(reg_name, reg_name_length);
1441 f += reg_name_length;
1442 register_offset = strtoll(f, &end, 0);
1443 if (f < end)
1444 f = end;
1445 if ((open_scope_ch == '{' && *f != '}') || (open_scope_ch == '[' && *f != ']'))
1446 {
1447 fprintf(file, "error: Invalid register format string. Valid formats are %%{regname} or %%{regname+offset}, %%[regname] or %%[regname+offset]\n");
1448 return total_bytes_read;
1449 }
1450 else
1451 {
1452 f++;
1453 if (DNBThreadGetRegisterValueByName(pid, tid, REGISTER_SET_ALL, register_name.c_str(), &register_value))
1454 {
1455 // Set the address to dereference using the register value plus the offset
1456 switch (register_value.info.size)
1457 {
1458 default:
1459 case 0:
1460 fprintf (file, "error: unsupported register size of %u.\n", register_value.info.size);
1461 return total_bytes_read;
1462
1463 case 1: register_addr = register_value.value.uint8 + register_offset; break;
1464 case 2: register_addr = register_value.value.uint16 + register_offset; break;
1465 case 4: register_addr = register_value.value.uint32 + register_offset; break;
1466 case 8: register_addr = register_value.value.uint64 + register_offset; break;
1467 case 16:
1468 if (open_scope_ch == '[')
1469 {
1470 fprintf (file, "error: register size (%u) too large for address.\n", register_value.info.size);
1471 return total_bytes_read;
1472 }
1473 break;
1474 }
1475
1476 if (open_scope_ch == '{')
1477 {
1478 byte_size = register_value.info.size;
1479 is_register = true; // value is in a register
1480
1481 }
1482 else
1483 {
1484 addr = register_addr; // Use register value and offset as the address
1485 }
1486 }
1487 else
1488 {
Jason Molenda1c739112013-02-22 07:27:08 +00001489 fprintf(file, "error: unable to read register '%s' for process %#.4x and thread %#.8" PRIx64 "\n", register_name.c_str(), pid, tid);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001490 return total_bytes_read;
1491 }
1492 }
1493 }
1494 }
1495 break;
1496
1497 default:
1498 fprintf(file, "error: %%$ must be followed by (regname + n) or [regname + n]\n");
1499 return total_bytes_read;
1500 }
1501 }
1502 break;
1503 }
1504
1505 // Check for a minimum field width
1506 if (isdigit(*f))
1507 {
Greg Clayton23f59502012-07-17 03:23:13 +00001508 //min_field_width = strtoul(f, &end, 10);
1509 strtoul(f, &end, 10);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001510 if (end > f)
1511 {
1512 fprintf_format.append(f, end - f);
1513 f = end;
1514 }
1515 }
1516
1517
1518 // Check for a precision
1519 if (*f == '.')
1520 {
1521 f++;
1522 if (isdigit(*f))
1523 {
1524 fprintf_format += '.';
Greg Clayton23f59502012-07-17 03:23:13 +00001525 //precision = strtoul(f, &end, 10);
1526 strtoul(f, &end, 10);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001527 if (end > f)
1528 {
1529 fprintf_format.append(f, end - f);
1530 f = end;
1531 }
1532 }
1533 }
1534
1535
1536 // mprintf specific: read the optional actual byte size (abs)
1537 // after the standard minimum field width (mfw) and precision (prec).
1538 // Standard printf calls you can have "mfw.prec" or ".prec", but
1539 // mprintf can have "mfw.prec.abs", ".prec.abs" or "..abs". This is nice
1540 // for strings that may be in a fixed size buffer, but may not use all bytes
1541 // in that buffer for printable characters.
1542 if (*f == '.')
1543 {
1544 f++;
1545 actual_byte_size = strtoul(f, &end, 10);
1546 if (end > f)
1547 {
1548 byte_size = actual_byte_size;
1549 f = end;
1550 }
1551 }
1552
1553 // Decode the length modifiers
1554 switch (*f)
1555 {
1556 case 'h': // h and hh length modifiers
1557 fprintf_format += *f++;
1558 length_modifiers |= length_mod_h;
1559 if (*f == 'h')
1560 {
1561 fprintf_format += *f++;
1562 length_modifiers |= length_mod_hh;
1563 }
1564 break;
1565
1566 case 'l': // l and ll length modifiers
1567 fprintf_format += *f++;
1568 length_modifiers |= length_mod_l;
1569 if (*f == 'h')
1570 {
1571 fprintf_format += *f++;
1572 length_modifiers |= length_mod_ll;
1573 }
1574 break;
1575
1576 case 'L': fprintf_format += *f++; length_modifiers |= length_mod_L; break;
1577 case 'j': fprintf_format += *f++; length_modifiers |= length_mod_j; break;
1578 case 't': fprintf_format += *f++; length_modifiers |= length_mod_t; break;
1579 case 'z': fprintf_format += *f++; length_modifiers |= length_mod_z; break;
1580 case 'q': fprintf_format += *f++; length_modifiers |= length_mod_q; break;
1581 }
1582
1583 // Decode the conversion specifier
1584 switch (*f)
1585 {
1586 case '_':
1587 // mprintf specific format items
1588 {
1589 ++f; // Skip the '_' character
1590 switch (*f)
1591 {
1592 case 'a': // Print the current address
1593 ++f;
1594 fprintf_format += "ll";
Bruce Mitcheneraaa0ba32014-07-08 18:05:41 +00001595 fprintf_format += *f; // actual format to show address with follows the 'a' ("%_ax")
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001596 fprintf (file, fprintf_format.c_str(), addr);
1597 break;
1598 case 'o': // offset from base address
1599 ++f;
1600 fprintf_format += "ll";
Bruce Mitcheneraaa0ba32014-07-08 18:05:41 +00001601 fprintf_format += *f; // actual format to show address with follows the 'a' ("%_ox")
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001602 fprintf(file, fprintf_format.c_str(), addr - base_addr);
1603 break;
1604 default:
1605 fprintf (file, "error: unsupported mprintf specific format character '%c'.\n", *f);
1606 break;
1607 }
1608 continue;
1609 }
1610 break;
1611
1612 case 'D':
1613 case 'O':
1614 case 'U':
1615 fprintf_format += *f;
1616 if (byte_size == 0)
1617 byte_size = sizeof(long int);
1618 break;
1619
1620 case 'd':
1621 case 'i':
1622 case 'o':
1623 case 'u':
1624 case 'x':
1625 case 'X':
1626 fprintf_format += *f;
1627 if (byte_size == 0)
1628 {
1629 if (length_modifiers & length_mod_hh)
1630 byte_size = sizeof(char);
1631 else if (length_modifiers & length_mod_h)
1632 byte_size = sizeof(short);
Greg Clayton23f59502012-07-17 03:23:13 +00001633 else if (length_modifiers & length_mod_ll)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001634 byte_size = sizeof(long long);
1635 else if (length_modifiers & length_mod_l)
1636 byte_size = sizeof(long);
1637 else
1638 byte_size = sizeof(int);
1639 }
1640 break;
1641
1642 case 'a':
1643 case 'A':
1644 case 'f':
1645 case 'F':
1646 case 'e':
1647 case 'E':
1648 case 'g':
1649 case 'G':
1650 fprintf_format += *f;
1651 if (byte_size == 0)
1652 {
1653 if (length_modifiers & length_mod_L)
1654 byte_size = sizeof(long double);
1655 else
1656 byte_size = sizeof(double);
1657 }
1658 break;
1659
1660 case 'c':
1661 if ((length_modifiers & length_mod_l) == 0)
1662 {
1663 fprintf_format += *f;
1664 if (byte_size == 0)
1665 byte_size = sizeof(char);
1666 break;
1667 }
1668 // Fall through to 'C' modifier below...
1669
1670 case 'C':
1671 fprintf_format += *f;
1672 if (byte_size == 0)
1673 byte_size = sizeof(wchar_t);
1674 break;
1675
1676 case 's':
1677 fprintf_format += *f;
1678 if (is_register || byte_size == 0)
1679 is_string = 1;
1680 break;
1681
1682 case 'p':
1683 fprintf_format += *f;
1684 if (byte_size == 0)
1685 byte_size = sizeof(void*);
1686 break;
1687 }
1688
1689 if (is_string)
1690 {
1691 std::string mem_string;
1692 const size_t string_buf_len = 4;
1693 char string_buf[string_buf_len+1];
1694 char *string_buf_end = string_buf + string_buf_len;
1695 string_buf[string_buf_len] = '\0';
1696 nub_size_t bytes_read;
1697 nub_addr_t str_addr = is_register ? register_addr : addr;
1698 while ((bytes_read = DNBProcessMemoryRead(pid, str_addr, string_buf_len, &string_buf[0])) > 0)
1699 {
1700 // Did we get a NULL termination character yet?
1701 if (strchr(string_buf, '\0') == string_buf_end)
1702 {
1703 // no NULL terminator yet, append as a std::string
1704 mem_string.append(string_buf, string_buf_len);
1705 str_addr += string_buf_len;
1706 }
1707 else
1708 {
1709 // yep
1710 break;
1711 }
1712 }
1713 // Append as a C-string so we don't get the extra NULL
1714 // characters in the temp buffer (since it was resized)
1715 mem_string += string_buf;
1716 size_t mem_string_len = mem_string.size() + 1;
1717 fprintf(file, fprintf_format.c_str(), mem_string.c_str());
1718 if (mem_string_len > 0)
1719 {
1720 if (!is_register)
1721 {
1722 addr += mem_string_len;
1723 total_bytes_read += mem_string_len;
1724 }
1725 }
1726 else
1727 return total_bytes_read;
1728 }
1729 else
1730 if (byte_size > 0)
1731 {
1732 buf.resize(byte_size);
1733 nub_size_t bytes_read = 0;
1734 if (is_register)
1735 bytes_read = register_value.info.size;
1736 else
1737 bytes_read = DNBProcessMemoryRead(pid, addr, buf.size(), &buf[0]);
1738 if (bytes_read > 0)
1739 {
1740 if (!is_register)
1741 total_bytes_read += bytes_read;
1742
1743 if (bytes_read == byte_size)
1744 {
1745 switch (*f)
1746 {
1747 case 'd':
1748 case 'i':
1749 case 'o':
1750 case 'u':
1751 case 'X':
1752 case 'x':
1753 case 'a':
1754 case 'A':
1755 case 'f':
1756 case 'F':
1757 case 'e':
1758 case 'E':
1759 case 'g':
1760 case 'G':
1761 case 'p':
1762 case 'c':
1763 case 'C':
1764 {
1765 if (is_register)
1766 data.SetData(&register_value.value.v_uint8[0], register_value.info.size);
1767 else
1768 data.SetData(&buf[0], bytes_read);
1769 DNBDataRef::offset_t data_offset = 0;
1770 if (byte_size <= 4)
1771 {
1772 uint32_t u32 = data.GetMax32(&data_offset, byte_size);
1773 // Show the actual byte width when displaying hex
1774 fprintf(file, fprintf_format.c_str(), u32);
1775 }
1776 else if (byte_size <= 8)
1777 {
1778 uint64_t u64 = data.GetMax64(&data_offset, byte_size);
1779 // Show the actual byte width when displaying hex
1780 fprintf(file, fprintf_format.c_str(), u64);
1781 }
1782 else
1783 {
1784 fprintf(file, "error: integer size not supported, must be 8 bytes or less (%u bytes).\n", byte_size);
1785 }
1786 if (!is_register)
1787 addr += byte_size;
1788 }
1789 break;
1790
1791 case 's':
1792 fprintf(file, fprintf_format.c_str(), buf.c_str());
1793 addr += byte_size;
1794 break;
1795
1796 default:
1797 fprintf(file, "error: unsupported conversion specifier '%c'.\n", *f);
1798 break;
1799 }
1800 }
1801 }
1802 }
1803 else
1804 return total_bytes_read;
1805 }
1806 break;
1807
1808 case '\\':
1809 {
1810 f++;
1811 switch (*f)
1812 {
1813 case 'e': ch = '\e'; break;
1814 case 'a': ch = '\a'; break;
1815 case 'b': ch = '\b'; break;
1816 case 'f': ch = '\f'; break;
1817 case 'n': ch = '\n'; break;
1818 case 'r': ch = '\r'; break;
1819 case 't': ch = '\t'; break;
1820 case 'v': ch = '\v'; break;
1821 case '\'': ch = '\''; break;
1822 case '\\': ch = '\\'; break;
1823 case '0':
1824 case '1':
1825 case '2':
1826 case '3':
1827 case '4':
1828 case '5':
1829 case '6':
1830 case '7':
1831 ch = strtoul(f, &end, 8);
1832 f = end;
1833 break;
1834 default:
1835 ch = *f;
1836 break;
1837 }
1838 fputc(ch, file);
1839 }
1840 break;
1841
1842 default:
1843 fputc(ch, file);
1844 break;
1845 }
1846 }
1847 return total_bytes_read;
1848}
1849
1850
1851//----------------------------------------------------------------------
1852// Get the number of threads for the specified process.
1853//----------------------------------------------------------------------
1854nub_size_t
1855DNBProcessGetNumThreads (nub_process_t pid)
1856{
1857 MachProcessSP procSP;
1858 if (GetProcessSP (pid, procSP))
1859 return procSP->GetNumThreads();
1860 return 0;
1861}
1862
1863//----------------------------------------------------------------------
1864// Get the thread ID of the current thread.
1865//----------------------------------------------------------------------
1866nub_thread_t
1867DNBProcessGetCurrentThread (nub_process_t pid)
1868{
1869 MachProcessSP procSP;
1870 if (GetProcessSP (pid, procSP))
1871 return procSP->GetCurrentThread();
1872 return 0;
1873}
1874
1875//----------------------------------------------------------------------
Jason Molendad5318c02013-04-03 04:18:47 +00001876// Get the mach port number of the current thread.
1877//----------------------------------------------------------------------
1878nub_thread_t
1879DNBProcessGetCurrentThreadMachPort (nub_process_t pid)
1880{
1881 MachProcessSP procSP;
1882 if (GetProcessSP (pid, procSP))
1883 return procSP->GetCurrentThreadMachPort();
1884 return 0;
1885}
1886
1887//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001888// Change the current thread.
1889//----------------------------------------------------------------------
1890nub_thread_t
1891DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid)
1892{
1893 MachProcessSP procSP;
1894 if (GetProcessSP (pid, procSP))
1895 return procSP->SetCurrentThread (tid);
1896 return INVALID_NUB_THREAD;
1897}
1898
1899
1900//----------------------------------------------------------------------
1901// Dump a string describing a thread's stop reason to the specified file
1902// handle
1903//----------------------------------------------------------------------
1904nub_bool_t
1905DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
1906{
1907 MachProcessSP procSP;
1908 if (GetProcessSP (pid, procSP))
1909 return procSP->GetThreadStoppedReason (tid, stop_info);
1910 return false;
1911}
1912
1913//----------------------------------------------------------------------
1914// Return string description for the specified thread.
1915//
1916// RETURNS: NULL if the thread isn't valid, else a NULL terminated C
1917// string from a static buffer that must be copied prior to subsequent
1918// calls.
1919//----------------------------------------------------------------------
1920const char *
1921DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid)
1922{
1923 MachProcessSP procSP;
1924 if (GetProcessSP (pid, procSP))
1925 return procSP->GetThreadInfo (tid);
1926 return NULL;
1927}
1928
1929//----------------------------------------------------------------------
1930// Get the thread ID given a thread index.
1931//----------------------------------------------------------------------
1932nub_thread_t
1933DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx)
1934{
1935 MachProcessSP procSP;
1936 if (GetProcessSP (pid, procSP))
1937 return procSP->GetThreadAtIndex (thread_idx);
1938 return INVALID_NUB_THREAD;
1939}
1940
Jim Ingham279ceec2012-07-25 21:12:43 +00001941//----------------------------------------------------------------------
1942// Do whatever is needed to sync the thread's register state with it's kernel values.
1943//----------------------------------------------------------------------
1944nub_bool_t
1945DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid)
1946{
1947 MachProcessSP procSP;
1948 if (GetProcessSP (pid, procSP))
1949 return procSP->SyncThreadState (tid);
1950 return false;
1951
1952}
1953
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001954nub_addr_t
1955DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid)
1956{
1957 MachProcessSP procSP;
1958 DNBError err;
1959 if (GetProcessSP (pid, procSP))
1960 return procSP->Task().GetDYLDAllImageInfosAddress (err);
1961 return INVALID_NUB_ADDRESS;
1962}
1963
1964
1965nub_bool_t
1966DNBProcessSharedLibrariesUpdated(nub_process_t pid)
1967{
1968 MachProcessSP procSP;
1969 if (GetProcessSP (pid, procSP))
1970 {
1971 procSP->SharedLibrariesUpdated ();
1972 return true;
1973 }
1974 return false;
1975}
1976
1977//----------------------------------------------------------------------
1978// Get the current shared library information for a process. Only return
1979// the shared libraries that have changed since the last shared library
1980// state changed event if only_changed is non-zero.
1981//----------------------------------------------------------------------
1982nub_size_t
1983DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos)
1984{
1985 MachProcessSP procSP;
1986 if (GetProcessSP (pid, procSP))
1987 return procSP->CopyImageInfos (image_infos, only_changed);
1988
1989 // If we have no process, then return NULL for the shared library info
1990 // and zero for shared library count
1991 *image_infos = NULL;
1992 return 0;
1993}
1994
1995//----------------------------------------------------------------------
1996// Get the register set information for a specific thread.
1997//----------------------------------------------------------------------
1998const DNBRegisterSetInfo *
1999DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
2000{
Greg Clayton3af9ea52010-11-18 05:57:03 +00002001 return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002002}
2003
2004
2005//----------------------------------------------------------------------
2006// Read a register value by register set and register index.
2007//----------------------------------------------------------------------
2008nub_bool_t
2009DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value)
2010{
2011 MachProcessSP procSP;
2012 ::bzero (value, sizeof(DNBRegisterValue));
2013 if (GetProcessSP (pid, procSP))
2014 {
2015 if (tid != INVALID_NUB_THREAD)
2016 return procSP->GetRegisterValue (tid, set, reg, value);
2017 }
2018 return false;
2019}
2020
2021nub_bool_t
2022DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value)
2023{
2024 if (tid != INVALID_NUB_THREAD)
2025 {
2026 MachProcessSP procSP;
2027 if (GetProcessSP (pid, procSP))
2028 return procSP->SetRegisterValue (tid, set, reg, value);
2029 }
2030 return false;
2031}
2032
2033nub_size_t
2034DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len)
2035{
2036 MachProcessSP procSP;
2037 if (GetProcessSP (pid, procSP))
2038 {
2039 if (tid != INVALID_NUB_THREAD)
2040 return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len);
2041 }
2042 ::bzero (buf, buf_len);
2043 return 0;
2044
2045}
2046
2047nub_size_t
2048DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len)
2049{
2050 MachProcessSP procSP;
2051 if (GetProcessSP (pid, procSP))
2052 {
2053 if (tid != INVALID_NUB_THREAD)
2054 return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len);
2055 }
2056 return 0;
2057}
2058
Greg Claytonf74cf862013-11-13 23:28:31 +00002059uint32_t
2060DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid)
2061{
2062 if (tid != INVALID_NUB_THREAD)
2063 {
2064 MachProcessSP procSP;
2065 if (GetProcessSP (pid, procSP))
2066 return procSP->GetThreadList().SaveRegisterState (tid);
2067 }
2068 return 0;
2069}
2070nub_bool_t
2071DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id)
2072{
2073 if (tid != INVALID_NUB_THREAD)
2074 {
2075 MachProcessSP procSP;
2076 if (GetProcessSP (pid, procSP))
2077 return procSP->GetThreadList().RestoreRegisterState (tid, save_id);
2078 }
2079 return false;
2080}
2081
2082
2083
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002084//----------------------------------------------------------------------
2085// Read a register value by name.
2086//----------------------------------------------------------------------
2087nub_bool_t
2088DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value)
2089{
2090 MachProcessSP procSP;
2091 ::bzero (value, sizeof(DNBRegisterValue));
2092 if (GetProcessSP (pid, procSP))
2093 {
2094 const struct DNBRegisterSetInfo *set_info;
2095 nub_size_t num_reg_sets = 0;
2096 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
2097 if (set_info)
2098 {
2099 uint32_t set = reg_set;
2100 uint32_t reg;
2101 if (set == REGISTER_SET_ALL)
2102 {
2103 for (set = 1; set < num_reg_sets; ++set)
2104 {
2105 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2106 {
2107 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
2108 return procSP->GetRegisterValue (tid, set, reg, value);
2109 }
2110 }
2111 }
2112 else
2113 {
2114 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2115 {
2116 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
2117 return procSP->GetRegisterValue (tid, set, reg, value);
2118 }
2119 }
2120 }
2121 }
2122 return false;
2123}
2124
2125
2126//----------------------------------------------------------------------
2127// Read a register set and register number from the register name.
2128//----------------------------------------------------------------------
2129nub_bool_t
2130DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info)
2131{
2132 const struct DNBRegisterSetInfo *set_info;
2133 nub_size_t num_reg_sets = 0;
2134 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
2135 if (set_info)
2136 {
2137 uint32_t set, reg;
2138 for (set = 1; set < num_reg_sets; ++set)
2139 {
2140 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2141 {
2142 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
2143 {
2144 *info = set_info[set].registers[reg];
2145 return true;
2146 }
2147 }
2148 }
2149
2150 for (set = 1; set < num_reg_sets; ++set)
2151 {
2152 uint32_t reg;
2153 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2154 {
2155 if (set_info[set].registers[reg].alt == NULL)
2156 continue;
2157
2158 if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0)
2159 {
2160 *info = set_info[set].registers[reg];
2161 return true;
2162 }
2163 }
2164 }
2165 }
2166
2167 ::bzero (info, sizeof(DNBRegisterInfo));
2168 return false;
2169}
2170
2171
2172//----------------------------------------------------------------------
2173// Set the name to address callback function that this nub can use
2174// for any name to address lookups that are needed.
2175//----------------------------------------------------------------------
2176nub_bool_t
2177DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton)
2178{
2179 MachProcessSP procSP;
2180 if (GetProcessSP (pid, procSP))
2181 {
2182 procSP->SetNameToAddressCallback (callback, baton);
2183 return true;
2184 }
2185 return false;
2186}
2187
2188
2189//----------------------------------------------------------------------
2190// Set the name to address callback function that this nub can use
2191// for any name to address lookups that are needed.
2192//----------------------------------------------------------------------
2193nub_bool_t
2194DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton)
2195{
2196 MachProcessSP procSP;
2197 if (GetProcessSP (pid, procSP))
2198 {
2199 procSP->SetSharedLibraryInfoCallback (callback, baton);
2200 return true;
2201 }
2202 return false;
2203}
2204
2205nub_addr_t
2206DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib)
2207{
2208 MachProcessSP procSP;
2209 if (GetProcessSP (pid, procSP))
2210 {
2211 return procSP->LookupSymbol (name, shlib);
2212 }
2213 return INVALID_NUB_ADDRESS;
2214}
2215
2216
2217nub_size_t
2218DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size)
2219{
2220 MachProcessSP procSP;
2221 if (GetProcessSP (pid, procSP))
2222 return procSP->GetAvailableSTDOUT (buf, buf_size);
2223 return 0;
2224}
2225
2226nub_size_t
2227DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size)
2228{
2229 MachProcessSP procSP;
2230 if (GetProcessSP (pid, procSP))
2231 return procSP->GetAvailableSTDERR (buf, buf_size);
2232 return 0;
2233}
2234
2235nub_size_t
Han Ming Ongab3b8b22012-11-17 00:21:04 +00002236DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size)
2237{
2238 MachProcessSP procSP;
2239 if (GetProcessSP (pid, procSP))
2240 return procSP->GetAsyncProfileData (buf, buf_size);
2241 return 0;
2242}
2243
2244nub_size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002245DNBProcessGetStopCount (nub_process_t pid)
2246{
2247 MachProcessSP procSP;
2248 if (GetProcessSP (pid, procSP))
2249 return procSP->StopCount();
2250 return 0;
2251}
2252
Greg Clayton71337622011-02-24 22:24:29 +00002253uint32_t
2254DNBProcessGetCPUType (nub_process_t pid)
2255{
2256 MachProcessSP procSP;
2257 if (GetProcessSP (pid, procSP))
2258 return procSP->GetCPUType ();
2259 return 0;
2260
2261}
2262
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002263nub_bool_t
2264DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
2265{
2266 if (path == NULL || path[0] == '\0')
2267 return false;
2268
2269 char max_path[PATH_MAX];
2270 std::string result;
2271 CFString::GlobPath(path, result);
2272
2273 if (result.empty())
2274 result = path;
Greg Clayton48baf7a2012-10-31 21:44:39 +00002275
2276 struct stat path_stat;
2277 if (::stat(path, &path_stat) == 0)
2278 {
2279 if ((path_stat.st_mode & S_IFMT) == S_IFDIR)
2280 {
2281 CFBundle bundle (path);
2282 CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
2283 if (url.get())
2284 {
2285 if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size))
2286 return true;
2287 }
2288 }
2289 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002290
2291 if (realpath(path, max_path))
2292 {
2293 // Found the path relatively...
2294 ::strncpy(resolved_path, max_path, resolved_path_size);
2295 return strlen(resolved_path) + 1 < resolved_path_size;
2296 }
2297 else
2298 {
2299 // Not a relative path, check the PATH environment variable if the
2300 const char *PATH = getenv("PATH");
2301 if (PATH)
2302 {
2303 const char *curr_path_start = PATH;
2304 const char *curr_path_end;
2305 while (curr_path_start && *curr_path_start)
2306 {
2307 curr_path_end = strchr(curr_path_start, ':');
2308 if (curr_path_end == NULL)
2309 {
2310 result.assign(curr_path_start);
2311 curr_path_start = NULL;
2312 }
2313 else if (curr_path_end > curr_path_start)
2314 {
2315 size_t len = curr_path_end - curr_path_start;
2316 result.assign(curr_path_start, len);
2317 curr_path_start += len + 1;
2318 }
2319 else
2320 break;
2321
2322 result += '/';
2323 result += path;
2324 struct stat s;
2325 if (stat(result.c_str(), &s) == 0)
2326 {
2327 ::strncpy(resolved_path, result.c_str(), resolved_path_size);
2328 return result.size() + 1 < resolved_path_size;
2329 }
2330 }
2331 }
2332 }
2333 return false;
2334}
2335
Greg Clayton3af9ea52010-11-18 05:57:03 +00002336
2337void
2338DNBInitialize()
2339{
2340 DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
2341#if defined (__i386__) || defined (__x86_64__)
2342 DNBArchImplI386::Initialize();
2343 DNBArchImplX86_64::Initialize();
Todd Fiala013434e2014-07-09 01:29:05 +00002344#elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
Greg Clayton3af9ea52010-11-18 05:57:03 +00002345 DNBArchMachARM::Initialize();
Jason Molendaa3329782014-03-29 18:54:20 +00002346 DNBArchMachARM64::Initialize();
Greg Clayton3af9ea52010-11-18 05:57:03 +00002347#endif
2348}
2349
2350void
2351DNBTerminate()
2352{
2353}
Greg Clayton3c144382010-12-01 22:45:40 +00002354
2355nub_bool_t
2356DNBSetArchitecture (const char *arch)
2357{
2358 if (arch && arch[0])
2359 {
2360 if (strcasecmp (arch, "i386") == 0)
2361 return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386);
Greg Claytona86dc432014-01-22 23:42:03 +00002362 else if ((strcasecmp (arch, "x86_64") == 0) || (strcasecmp (arch, "x86_64h") == 0))
Greg Clayton3c144382010-12-01 22:45:40 +00002363 return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64);
Todd Fiala013434e2014-07-09 01:29:05 +00002364 else if (strstr (arch, "arm64") == arch || strstr (arch, "armv8") == arch || strstr (arch, "aarch64") == arch)
Jason Molendaa3329782014-03-29 18:54:20 +00002365 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM64);
Greg Clayton3c144382010-12-01 22:45:40 +00002366 else if (strstr (arch, "arm") == arch)
2367 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM);
2368 }
2369 return false;
2370}