blob: 03c85df441de4c92ff4a58e92a09ad8a6c3c0b20 [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//----------------------------------------------------------------------
Greg Claytonee2ed522015-03-09 19:45:23 +0000109//static size_t
110//RemoveProcessFromMap (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//}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119
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 {
Greg Claytonee2ed522015-03-09 19:45:23 +0000178 int error_no = static_cast<int>(death_event.data);
179 const char *error_str = strerror(error_no);
Jason Molendaa3329782014-03-29 18:54:20 +0000180 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;
Greg Clayton040c5602014-04-30 20:24:10 +0000195 if (WIFSTOPPED(status))
196 {
197 signal = WSTOPSIG(status);
Greg Clayton040c5602014-04-30 20:24:10 +0000198 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)", child_pid, signal);
199 }
200 else if (WIFEXITED(status))
201 {
202 exit_status = WEXITSTATUS(status);
Greg Clayton040c5602014-04-30 20:24:10 +0000203 exited = true;
204 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)", child_pid, exit_status);
205 }
206 else if (WIFSIGNALED(status))
207 {
208 signal = WTERMSIG(status);
Greg Clayton040c5602014-04-30 20:24:10 +0000209 if (child_pid == abs(pid))
210 {
211 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED and EXITED (signal = %i)", child_pid, signal);
212 char exit_info[64];
213 ::snprintf (exit_info, sizeof(exit_info), "Terminated due to signal %i", signal);
214 DNBProcessSetExitInfo (child_pid, exit_info);
215 exited = true;
216 exit_status = INT8_MAX;
217 }
218 else
219 {
220 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED (signal = %i)", child_pid, signal);
221 }
222 }
223
224 if (exited)
225 {
226 if (death_event.data & NOTE_EXIT_MEMORY)
Jim Ingham0c7ebe92014-06-17 21:02:44 +0000227 DNBProcessSetExitInfo (child_pid, "Terminated due to memory issue");
Greg Clayton040c5602014-04-30 20:24:10 +0000228 else if (death_event.data & NOTE_EXIT_DECRYPTFAIL)
229 DNBProcessSetExitInfo (child_pid, "Terminated due to decrypt failure");
230 else if (death_event.data & NOTE_EXIT_CSERROR)
231 DNBProcessSetExitInfo (child_pid, "Terminated due to code signing error");
232
233 DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, exit_status);
234 DNBProcessSetExitStatus (child_pid, status);
235 return NULL;
236 }
Jason Molendaa3329782014-03-29 18:54:20 +0000237 }
238 }
239}
240
241static bool
242spawn_kqueue_thread (pid_t pid)
243{
244 pthread_t thread;
245 int kq_id;
246
247 kq_id = kqueue();
248 if (kq_id == -1)
249 {
250 DNBLogError ("Could not get kqueue for pid = %i.", pid);
251 return false;
252 }
253
254 struct kevent reg_event;
255
Jim Ingham60089242014-06-24 21:51:42 +0000256 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 +0000257 // Register the event:
258 int result = kevent (kq_id, &reg_event, 1, NULL, 0, NULL);
259 if (result != 0)
260 {
261 DNBLogError ("Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, result);
262 return false;
263 }
264
265 int ret = ::pthread_create (&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id);
266
267 // pthread_create returns 0 if successful
268 if (ret == 0)
269 {
270 ::pthread_detach (thread);
271 return true;
272 }
273 return false;
274}
275#endif // #if USE_KQUEUE
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000276
277static void *
278waitpid_thread (void *arg)
279{
280 const pid_t pid = (pid_t)(intptr_t)arg;
281 int status;
Jason Molenda36a216e2014-07-24 01:36:24 +0000282
283#if defined (__APPLE__)
284 pthread_setname_np ("waitpid thread");
285#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
286 struct sched_param thread_param;
287 int thread_sched_policy;
288 if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0)
289 {
290 thread_param.sched_priority = 47;
291 pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
292 }
293#endif
294#endif
295
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000296 while (1)
297 {
298 pid_t child_pid = waitpid(pid, &status, 0);
Greg Clayton6467ff92013-06-27 00:23:57 +0000299 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 +0000300
301 if (child_pid < 0)
302 {
303 if (errno == EINTR)
304 continue;
305 break;
306 }
307 else
308 {
309 if (WIFSTOPPED(status))
310 {
311 continue;
312 }
313 else// if (WIFEXITED(status) || WIFSIGNALED(status))
314 {
Greg Clayton6467ff92013-06-27 00:23:57 +0000315 DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): setting exit status for pid = %i to %i", child_pid, status);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000316 DNBProcessSetExitStatus (child_pid, status);
317 return NULL;
318 }
319 }
320 }
321
322 // We should never exit as long as our child process is alive, so if we
323 // do something else went wrong and we should exit...
Greg Clayton6467ff92013-06-27 00:23:57 +0000324 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 +0000325 DNBProcessSetExitStatus (pid, -1);
326 return NULL;
327}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000328static bool
329spawn_waitpid_thread (pid_t pid)
330{
Jason Molendaa3329782014-03-29 18:54:20 +0000331#ifdef USE_KQUEUE
332 bool success = spawn_kqueue_thread (pid);
333 if (success)
334 return true;
335#endif
336
Jason Molenda27148b32013-10-05 02:52:22 +0000337 pthread_t thread;
338 int ret = ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid);
339 // pthread_create returns 0 if successful
340 if (ret == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000341 {
342 ::pthread_detach (thread);
343 return true;
344 }
345 return false;
346}
347
348nub_process_t
349DNBProcessLaunch (const char *path,
350 char const *argv[],
351 const char *envp[],
Bruce Mitcheneraaa0ba32014-07-08 18:05:41 +0000352 const char *working_directory, // NULL => don't change, non-NULL => set working directory for inferior to this
Greg Clayton6779606a2011-01-22 23:43:18 +0000353 const char *stdin_path,
354 const char *stdout_path,
355 const char *stderr_path,
Caroline Ticef8da8632010-12-03 18:46:09 +0000356 bool no_stdio,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000357 nub_launch_flavor_t launch_flavor,
Greg Claytonf681b942010-08-31 18:35:14 +0000358 int disable_aslr,
Jason Molendaa3329782014-03-29 18:54:20 +0000359 const char *event_data,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000360 char *err_str,
361 size_t err_len)
362{
Greg Clayton43e0af02012-09-18 18:04:04 +0000363 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 +0000364 __FUNCTION__,
365 path,
366 argv,
367 envp,
368 working_directory,
369 stdin_path,
370 stdout_path,
371 stderr_path,
372 no_stdio,
373 launch_flavor,
374 disable_aslr,
375 err_str,
Greg Clayton43e0af02012-09-18 18:04:04 +0000376 (uint64_t)err_len);
Greg Claytonbd82a5d2011-01-23 05:56:20 +0000377
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000378 if (err_str && err_len > 0)
379 err_str[0] = '\0';
380 struct stat path_stat;
381 if (::stat(path, &path_stat) == -1)
382 {
383 char stat_error[256];
384 ::strerror_r (errno, stat_error, sizeof(stat_error));
385 snprintf(err_str, err_len, "%s (%s)", stat_error, path);
386 return INVALID_NUB_PROCESS;
387 }
388
389 MachProcessSP processSP (new MachProcess);
390 if (processSP.get())
391 {
392 DNBError launch_err;
Greg Clayton6779606a2011-01-22 23:43:18 +0000393 pid_t pid = processSP->LaunchForDebug (path,
394 argv,
395 envp,
396 working_directory,
397 stdin_path,
398 stdout_path,
399 stderr_path,
400 no_stdio,
401 launch_flavor,
Jason Molendaa3329782014-03-29 18:54:20 +0000402 disable_aslr,
403 event_data,
Greg Clayton6779606a2011-01-22 23:43:18 +0000404 launch_err);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000405 if (err_str)
406 {
407 *err_str = '\0';
408 if (launch_err.Fail())
409 {
410 const char *launch_err_str = launch_err.AsString();
411 if (launch_err_str)
412 {
413 strncpy(err_str, launch_err_str, err_len-1);
414 err_str[err_len-1] = '\0'; // Make sure the error string is terminated
415 }
416 }
417 }
418
419 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
420
421 if (pid != INVALID_NUB_PROCESS)
422 {
423 // Spawn a thread to reap our child inferior process...
424 spawn_waitpid_thread (pid);
425
426 if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL)
427 {
428 // We failed to get the task for our process ID which is bad.
Greg Claytonfb640c22012-02-02 19:23:22 +0000429 // Kill our process otherwise it will be stopped at the entry
430 // point and get reparented to someone else and never go away.
Jason Molenda153c8e02013-01-05 06:08:51 +0000431 DNBLog ("Could not get task port for process, sending SIGKILL and exiting.");
Greg Claytonfb640c22012-02-02 19:23:22 +0000432 kill (SIGKILL, pid);
433
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000434 if (err_str && err_len > 0)
435 {
436 if (launch_err.AsString())
437 {
438 ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString());
439 }
440 else
441 {
442 ::snprintf (err_str, err_len, "failed to get the task for process %i", pid);
443 }
444 }
445 }
446 else
447 {
Charles Davisb786e7d2012-02-21 00:53:12 +0000448 bool res = AddProcessToMap(pid, processSP);
Bruce Mitchener8a67bf72015-07-24 00:23:29 +0000449 UNUSED_IF_ASSERT_DISABLED(res);
Charles Davisb786e7d2012-02-21 00:53:12 +0000450 assert(res && "Couldn't add process to map!");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000451 return pid;
452 }
453 }
454 }
455 return INVALID_NUB_PROCESS;
456}
457
Jason Molenda752e1e82015-07-29 01:42:16 +0000458// If there is one process with a given name, return the pid for that process.
459nub_process_t
460DNBProcessGetPIDByName (const char *name)
461{
462 std::vector<struct kinfo_proc> matching_proc_infos;
463 size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
464 if (num_matching_proc_infos == 1)
465 {
466 return matching_proc_infos[0].kp_proc.p_pid;
467 }
468 return INVALID_NUB_PROCESS;
469}
470
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000471nub_process_t
472DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
473{
474 if (err_str && err_len > 0)
475 err_str[0] = '\0';
476 std::vector<struct kinfo_proc> matching_proc_infos;
477 size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
478 if (num_matching_proc_infos == 0)
479 {
480 DNBLogError ("error: no processes match '%s'\n", name);
481 return INVALID_NUB_PROCESS;
482 }
483 else if (num_matching_proc_infos > 1)
484 {
Greg Clayton43e0af02012-09-18 18:04:04 +0000485 DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000486 size_t i;
487 for (i=0; i<num_matching_proc_infos; ++i)
488 DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
489 return INVALID_NUB_PROCESS;
490 }
Greg Clayton3af9ea52010-11-18 05:57:03 +0000491
492 return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000493}
494
495nub_process_t
496DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len)
497{
498 if (err_str && err_len > 0)
499 err_str[0] = '\0';
500
Johnny Chen64503c82011-08-11 19:03:44 +0000501 pid_t pid = INVALID_NUB_PROCESS;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000502 MachProcessSP processSP(new MachProcess);
503 if (processSP.get())
504 {
505 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid);
506 pid = processSP->AttachForDebug (attach_pid, err_str, err_len);
507
508 if (pid != INVALID_NUB_PROCESS)
509 {
Charles Davisb786e7d2012-02-21 00:53:12 +0000510 bool res = AddProcessToMap(pid, processSP);
Bruce Mitchener8a67bf72015-07-24 00:23:29 +0000511 UNUSED_IF_ASSERT_DISABLED(res);
Charles Davisb786e7d2012-02-21 00:53:12 +0000512 assert(res && "Couldn't add process to map!");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000513 spawn_waitpid_thread(pid);
514 }
515 }
516
517 while (pid != INVALID_NUB_PROCESS)
518 {
519 // Wait for process to start up and hit entry point
Greg Clayton3af9ea52010-11-18 05:57:03 +0000520 DNBLogThreadedIf (LOG_PROCESS,
521 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
522 __FUNCTION__,
523 pid);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000524 nub_event_t set_events = DNBProcessWaitForEvents (pid,
Greg Clayton3af9ea52010-11-18 05:57:03 +0000525 eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
526 true,
527 timeout);
528
529 DNBLogThreadedIf (LOG_PROCESS,
530 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
531 __FUNCTION__,
532 pid,
533 set_events);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000534
535 if (set_events == 0)
536 {
537 if (err_str && err_len > 0)
538 snprintf(err_str, err_len, "operation timed out");
539 pid = INVALID_NUB_PROCESS;
540 }
541 else
542 {
543 if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
544 {
545 nub_state_t pid_state = DNBProcessGetState (pid);
546 DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s",
547 __FUNCTION__, pid, DNBStateAsString(pid_state));
548
549 switch (pid_state)
550 {
Greg Clayton3af9ea52010-11-18 05:57:03 +0000551 default:
552 case eStateInvalid:
553 case eStateUnloaded:
554 case eStateAttaching:
555 case eStateLaunching:
556 case eStateSuspended:
557 break; // Ignore
558
559 case eStateRunning:
560 case eStateStepping:
561 // Still waiting to stop at entry point...
562 break;
563
564 case eStateStopped:
565 case eStateCrashed:
566 return pid;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000567
Greg Clayton3af9ea52010-11-18 05:57:03 +0000568 case eStateDetached:
569 case eStateExited:
570 if (err_str && err_len > 0)
571 snprintf(err_str, err_len, "process exited");
572 return INVALID_NUB_PROCESS;
573 }
574 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000575
576 DNBProcessResetEvents(pid, set_events);
577 }
578 }
579
580 return INVALID_NUB_PROCESS;
581}
582
Greg Clayton9eb4e032012-11-06 23:36:26 +0000583size_t
Greg Clayton3af9ea52010-11-18 05:57:03 +0000584GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000585{
Greg Clayton9eb4e032012-11-06 23:36:26 +0000586 size_t size = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000587 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
Jim Inghamc1fdb882014-06-27 16:02:55 +0000588 u_int namelen = sizeof(name)/sizeof(int);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000589 int err;
590
591 // Try to find out how many processes are around so we can
592 // size the buffer appropriately. sysctl's man page specifically suggests
593 // this approach, and says it returns a bit larger size than needed to
594 // handle any new processes created between then and now.
595
596 err = ::sysctl (name, namelen, NULL, &size, NULL, 0);
597
598 if ((err < 0) && (err != ENOMEM))
599 {
600 proc_infos.clear();
601 perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
602 return 0;
603 }
604
605
606 // Increase the size of the buffer by a few processes in case more have
607 // been spawned
608 proc_infos.resize (size / sizeof(struct kinfo_proc));
609 size = proc_infos.size() * sizeof(struct kinfo_proc); // Make sure we don't exceed our resize...
610 err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0);
611 if (err < 0)
612 {
613 proc_infos.clear();
614 return 0;
615 }
616
617 // Trim down our array to fit what we actually got back
618 proc_infos.resize(size / sizeof(struct kinfo_proc));
619 return proc_infos.size();
620}
621
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000622static size_t
623GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos)
624{
625
626 matching_proc_infos.clear();
627 if (full_process_name && full_process_name[0])
628 {
629 // We only get the process name, not the full path, from the proc_info. So just take the
630 // base name of the process name...
631 const char *process_name;
632 process_name = strrchr (full_process_name, '/');
633 if (process_name == NULL)
Greg Clayton7dab2be2012-07-19 02:45:35 +0000634 process_name = full_process_name;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000635 else
Greg Clayton7dab2be2012-07-19 02:45:35 +0000636 process_name++;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000637
Greg Claytonee2ed522015-03-09 19:45:23 +0000638 const size_t process_name_len = strlen(process_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000639 std::vector<struct kinfo_proc> proc_infos;
640 const size_t num_proc_infos = GetAllInfos(proc_infos);
641 if (num_proc_infos > 0)
642 {
643 uint32_t i;
644 for (i=0; i<num_proc_infos; i++)
645 {
646 // Skip zombie processes and processes with unset status
647 if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB)
648 continue;
649
650 // Check for process by name. We only check the first MAXCOMLEN
651 // chars as that is all that kp_proc.p_comm holds.
Jim Ingham490bccd2012-11-01 01:04:46 +0000652
Greg Clayton7dab2be2012-07-19 02:45:35 +0000653 if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000654 {
Greg Clayton7dab2be2012-07-19 02:45:35 +0000655 if (process_name_len > MAXCOMLEN)
656 {
657 // We found a matching process name whose first MAXCOMLEN
658 // characters match, but there is more to the name than
Jim Ingham490bccd2012-11-01 01:04:46 +0000659 // this. We need to get the full process name. Use proc_pidpath, which will get
660 // us the full path to the executed process.
Greg Clayton7dab2be2012-07-19 02:45:35 +0000661
Jim Ingham490bccd2012-11-01 01:04:46 +0000662 char proc_path_buf[PATH_MAX];
Greg Clayton7dab2be2012-07-19 02:45:35 +0000663
Jim Ingham490bccd2012-11-01 01:04:46 +0000664 int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX);
665 if (return_val > 0)
Greg Clayton7dab2be2012-07-19 02:45:35 +0000666 {
Jim Ingham490bccd2012-11-01 01:04:46 +0000667 // Okay, now search backwards from that to see if there is a
668 // slash in the name. Note, even though we got all the args we don't care
669 // because the list data is just a bunch of concatenated null terminated strings
670 // so strrchr will start from the end of argv0.
671
672 const char *argv_basename = strrchr(proc_path_buf, '/');
Greg Clayton7dab2be2012-07-19 02:45:35 +0000673 if (argv_basename)
674 {
675 // Skip the '/'
676 ++argv_basename;
677 }
678 else
679 {
680 // 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 +0000681 argv_basename = proc_path_buf;
Greg Clayton7dab2be2012-07-19 02:45:35 +0000682 }
683
684 if (argv_basename)
685 {
686 if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0)
687 {
688 matching_proc_infos.push_back(proc_infos[i]);
689 }
690 }
691 }
692 }
693 else
694 {
695 // We found a matching process, add it to our list
Greg Clayton7dab2be2012-07-19 02:45:35 +0000696 matching_proc_infos.push_back(proc_infos[i]);
697 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000698 }
699 }
700 }
701 }
702 // return the newly added matches.
703 return matching_proc_infos.size();
704}
705
706nub_process_t
Greg Clayton19388cf2010-10-18 01:45:30 +0000707DNBProcessAttachWait (const char *waitfor_process_name,
708 nub_launch_flavor_t launch_flavor,
Jim Inghamcd16df92012-07-20 21:37:13 +0000709 bool ignore_existing,
Greg Clayton19388cf2010-10-18 01:45:30 +0000710 struct timespec *timeout_abstime,
711 useconds_t waitfor_interval,
712 char *err_str,
713 size_t err_len,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000714 DNBShouldCancelCallback should_cancel_callback,
715 void *callback_data)
716{
717 DNBError prepare_error;
718 std::vector<struct kinfo_proc> exclude_proc_infos;
719 size_t num_exclude_proc_infos;
720
721 // If the PrepareForAttach returns a valid token, use MachProcess to check
722 // for the process, otherwise scan the process table.
723
724 const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error);
725
726 if (prepare_error.Fail())
727 {
728 DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString());
729 return INVALID_NUB_PROCESS;
730 }
731
732 if (attach_token == NULL)
Jim Inghamcd16df92012-07-20 21:37:13 +0000733 {
734 if (ignore_existing)
735 num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
736 else
737 num_exclude_proc_infos = 0;
738 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000739
740 DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
741
742 // Loop and try to find the process by name
743 nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
744
745 while (waitfor_pid == INVALID_NUB_PROCESS)
746 {
747 if (attach_token != NULL)
748 {
749 nub_process_t pid;
Jason Molendac611a742015-10-23 02:49:51 +0000750 pid = MachProcess::CheckForProcess(attach_token, launch_flavor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000751 if (pid != INVALID_NUB_PROCESS)
752 {
753 waitfor_pid = pid;
754 break;
755 }
756 }
757 else
758 {
759
760 // Get the current process list, and check for matches that
761 // aren't in our original list. If anyone wants to attach
762 // to an existing process by name, they should do it with
763 // --attach=PROCNAME. Else we will wait for the first matching
764 // process that wasn't in our exclusion list.
765 std::vector<struct kinfo_proc> proc_infos;
766 const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos);
767 for (size_t i=0; i<num_proc_infos; i++)
768 {
769 nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
770 for (size_t j=0; j<num_exclude_proc_infos; j++)
771 {
772 if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid)
773 {
774 // This process was in our exclusion list, don't use it.
775 curr_pid = INVALID_NUB_PROCESS;
776 break;
777 }
778 }
779
780 // If we didn't find CURR_PID in our exclusion list, then use it.
781 if (curr_pid != INVALID_NUB_PROCESS)
782 {
783 // We found our process!
784 waitfor_pid = curr_pid;
785 break;
786 }
787 }
788 }
789
790 // If we haven't found our process yet, check for a timeout
791 // and then sleep for a bit until we poll again.
792 if (waitfor_pid == INVALID_NUB_PROCESS)
793 {
794 if (timeout_abstime != NULL)
795 {
796 // Check to see if we have a waitfor-duration option that
797 // has timed out?
798 if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime))
799 {
800 if (err_str && err_len > 0)
801 snprintf(err_str, err_len, "operation timed out");
802 DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name);
803 return INVALID_NUB_PROCESS;
804 }
805 }
806
807 // Call the should cancel callback as well...
808
809 if (should_cancel_callback != NULL
810 && should_cancel_callback (callback_data))
811 {
812 DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback.");
813 waitfor_pid = INVALID_NUB_PROCESS;
814 break;
815 }
816
817 ::usleep (waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again
818 }
819 }
820
821 if (waitfor_pid != INVALID_NUB_PROCESS)
822 {
823 DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid);
824 waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len);
825 }
826
827 bool success = waitfor_pid != INVALID_NUB_PROCESS;
Jason Molendac611a742015-10-23 02:49:51 +0000828 MachProcess::CleanupAfterAttach (attach_token, launch_flavor, success, prepare_error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000829
830 return waitfor_pid;
831}
832
833nub_bool_t
834DNBProcessDetach (nub_process_t pid)
835{
836 MachProcessSP procSP;
837 if (GetProcessSP (pid, procSP))
838 {
Jim Ingham58813182014-02-25 04:53:13 +0000839 const bool remove = true;
840 DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid);
841 procSP->DisableAllBreakpoints(remove);
842 procSP->DisableAllWatchpoints (remove);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000843 return procSP->Detach();
844 }
845 return false;
846}
847
848nub_bool_t
849DNBProcessKill (nub_process_t pid)
850{
851 MachProcessSP procSP;
852 if (GetProcessSP (pid, procSP))
853 {
854 return procSP->Kill ();
855 }
856 return false;
857}
858
859nub_bool_t
860DNBProcessSignal (nub_process_t pid, int signal)
861{
862 MachProcessSP procSP;
863 if (GetProcessSP (pid, procSP))
864 {
865 return procSP->Signal (signal);
866 }
867 return false;
868}
869
Greg Clayton4296c222014-04-24 19:54:32 +0000870
871nub_bool_t
872DNBProcessInterrupt(nub_process_t pid)
873{
874 MachProcessSP procSP;
875 if (GetProcessSP (pid, procSP))
876 return procSP->Interrupt();
877 return false;
878}
879
Jason Molendaa3329782014-03-29 18:54:20 +0000880nub_bool_t
881DNBProcessSendEvent (nub_process_t pid, const char *event)
882{
883 MachProcessSP procSP;
884 if (GetProcessSP (pid, procSP))
885 {
886 // FIXME: Do something with the error...
887 DNBError send_error;
888 return procSP->SendEvent (event, send_error);
889 }
890 return false;
891}
892
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000893
894nub_bool_t
895DNBProcessIsAlive (nub_process_t pid)
896{
897 MachProcessSP procSP;
898 if (GetProcessSP (pid, procSP))
899 {
900 return MachTask::IsValid (procSP->Task().TaskPort());
901 }
902 return eStateInvalid;
903}
904
905//----------------------------------------------------------------------
906// Process and Thread state information
907//----------------------------------------------------------------------
908nub_state_t
909DNBProcessGetState (nub_process_t pid)
910{
911 MachProcessSP procSP;
912 if (GetProcessSP (pid, procSP))
913 {
914 return procSP->GetState();
915 }
916 return eStateInvalid;
917}
918
919//----------------------------------------------------------------------
920// Process and Thread state information
921//----------------------------------------------------------------------
922nub_bool_t
923DNBProcessGetExitStatus (nub_process_t pid, int* status)
924{
925 MachProcessSP procSP;
926 if (GetProcessSP (pid, procSP))
927 {
928 return procSP->GetExitStatus(status);
929 }
930 return false;
931}
932
933nub_bool_t
934DNBProcessSetExitStatus (nub_process_t pid, int status)
935{
936 MachProcessSP procSP;
937 if (GetProcessSP (pid, procSP))
938 {
939 procSP->SetExitStatus(status);
940 return true;
941 }
942 return false;
943}
944
Jason Molendaa3329782014-03-29 18:54:20 +0000945const char *
946DNBProcessGetExitInfo (nub_process_t pid)
947{
948 MachProcessSP procSP;
949 if (GetProcessSP (pid, procSP))
950 {
951 return procSP->GetExitInfo();
952 }
953 return NULL;
954}
955
956nub_bool_t
957DNBProcessSetExitInfo (nub_process_t pid, const char *info)
958{
959 MachProcessSP procSP;
960 if (GetProcessSP (pid, procSP))
961 {
962 procSP->SetExitInfo(info);
963 return true;
964 }
965 return false;
966}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000967
968const char *
969DNBThreadGetName (nub_process_t pid, nub_thread_t tid)
970{
971 MachProcessSP procSP;
972 if (GetProcessSP (pid, procSP))
973 return procSP->ThreadGetName(tid);
974 return NULL;
975}
976
977
978nub_bool_t
979DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info)
980{
981 MachProcessSP procSP;
982 if (GetProcessSP (pid, procSP))
983 return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
984 return false;
985}
986
987nub_state_t
988DNBThreadGetState (nub_process_t pid, nub_thread_t tid)
989{
990 MachProcessSP procSP;
991 if (GetProcessSP (pid, procSP))
992 {
993 return procSP->ThreadGetState(tid);
994 }
995 return eStateInvalid;
996}
997
998const char *
999DNBStateAsString(nub_state_t state)
1000{
1001 switch (state)
1002 {
Greg Claytoneffe5c92011-05-03 22:09:39 +00001003 case eStateInvalid: return "Invalid";
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001004 case eStateUnloaded: return "Unloaded";
1005 case eStateAttaching: return "Attaching";
1006 case eStateLaunching: return "Launching";
1007 case eStateStopped: return "Stopped";
1008 case eStateRunning: return "Running";
1009 case eStateStepping: return "Stepping";
1010 case eStateCrashed: return "Crashed";
1011 case eStateDetached: return "Detached";
1012 case eStateExited: return "Exited";
1013 case eStateSuspended: return "Suspended";
1014 }
1015 return "nub_state_t ???";
1016}
1017
Jason Molenda705b1802014-06-13 02:37:02 +00001018Genealogy::ThreadActivitySP
1019DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out)
1020{
1021 Genealogy::ThreadActivitySP thread_activity_sp;
1022 MachProcessSP procSP;
1023 if (GetProcessSP (pid, procSP))
1024 thread_activity_sp = procSP->GetGenealogyInfoForThread (tid, timed_out);
1025 return thread_activity_sp;
1026}
1027
1028Genealogy::ProcessExecutableInfoSP
1029DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx)
1030{
1031 Genealogy::ProcessExecutableInfoSP image_info_sp;
1032 MachProcessSP procSP;
1033 if (GetProcessSP (pid, procSP))
1034 {
1035 image_info_sp = procSP->GetGenealogyImageInfo (idx);
1036 }
1037 return image_info_sp;
1038}
1039
1040ThreadInfo::QoS
1041DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index)
1042{
1043 MachProcessSP procSP;
1044 if (GetProcessSP (pid, procSP))
1045 {
1046 return procSP->GetRequestedQoS (tid, tsd, dti_qos_class_index);
1047 }
1048 return ThreadInfo::QoS();
1049}
1050
1051nub_addr_t
1052DNBGetPThreadT (nub_process_t pid, nub_thread_t tid)
1053{
1054 MachProcessSP procSP;
1055 if (GetProcessSP (pid, procSP))
1056 {
1057 return procSP->GetPThreadT (tid);
1058 }
1059 return INVALID_NUB_ADDRESS;
1060}
1061
1062nub_addr_t
1063DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid)
1064{
1065 MachProcessSP procSP;
1066 if (GetProcessSP (pid, procSP))
1067 {
1068 return procSP->GetDispatchQueueT (tid);
1069 }
1070 return INVALID_NUB_ADDRESS;
1071}
1072
1073nub_addr_t
1074DNBGetTSDAddressForThread (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)
1075{
1076 MachProcessSP procSP;
1077 if (GetProcessSP (pid, procSP))
1078 {
1079 return procSP->GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
1080 }
1081 return INVALID_NUB_ADDRESS;
1082}
1083
Jason Molenda20ee21b2015-07-10 23:15:22 +00001084JSONGenerator::ObjectSP
1085DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count)
1086{
1087 MachProcessSP procSP;
1088 if (GetProcessSP (pid, procSP))
1089 {
1090 return procSP->GetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count);
1091 }
1092 return JSONGenerator::ObjectSP();
1093}
1094
1095
Jason Molenda705b1802014-06-13 02:37:02 +00001096
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001097const char *
1098DNBProcessGetExecutablePath (nub_process_t pid)
1099{
1100 MachProcessSP procSP;
1101 if (GetProcessSP (pid, procSP))
1102 {
1103 return procSP->Path();
1104 }
1105 return NULL;
1106}
1107
1108nub_size_t
1109DNBProcessGetArgumentCount (nub_process_t pid)
1110{
1111 MachProcessSP procSP;
1112 if (GetProcessSP (pid, procSP))
1113 {
1114 return procSP->ArgumentCount();
1115 }
1116 return 0;
1117}
1118
1119const char *
1120DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx)
1121{
1122 MachProcessSP procSP;
1123 if (GetProcessSP (pid, procSP))
1124 {
1125 return procSP->ArgumentAtIndex (idx);
1126 }
1127 return NULL;
1128}
1129
1130
1131//----------------------------------------------------------------------
1132// Execution control
1133//----------------------------------------------------------------------
1134nub_bool_t
1135DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions)
1136{
1137 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1138 MachProcessSP procSP;
1139 if (GetProcessSP (pid, procSP))
1140 {
1141 DNBThreadResumeActions thread_actions (actions, num_actions);
1142
1143 // Below we add a default thread plan just in case one wasn't
1144 // provided so all threads always know what they were supposed to do
1145 if (thread_actions.IsEmpty())
1146 {
1147 // No thread plans were given, so the default it to run all threads
1148 thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
1149 }
1150 else
1151 {
1152 // Some thread plans were given which means anything that wasn't
1153 // specified should remain stopped.
1154 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
1155 }
1156 return procSP->Resume (thread_actions);
1157 }
1158 return false;
1159}
1160
1161nub_bool_t
1162DNBProcessHalt (nub_process_t pid)
1163{
1164 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1165 MachProcessSP procSP;
1166 if (GetProcessSP (pid, procSP))
1167 return procSP->Signal (SIGSTOP);
1168 return false;
1169}
1170//
1171//nub_bool_t
1172//DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
1173//{
1174// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step);
1175// MachProcessSP procSP;
1176// if (GetProcessSP (pid, procSP))
1177// {
1178// return procSP->Resume(tid, step, 0);
1179// }
1180// return false;
1181//}
1182//
1183//nub_bool_t
1184//DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal)
1185//{
1186// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
1187// MachProcessSP procSP;
1188// if (GetProcessSP (pid, procSP))
1189// {
1190// return procSP->Resume(tid, step, signal);
1191// }
1192// return false;
1193//}
1194
1195nub_event_t
1196DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout)
1197{
1198 nub_event_t result = 0;
1199 MachProcessSP procSP;
1200 if (GetProcessSP (pid, procSP))
1201 {
1202 if (wait_for_set)
1203 result = procSP->Events().WaitForSetEvents(event_mask, timeout);
1204 else
1205 result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
1206 }
1207 return result;
1208}
1209
1210void
1211DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask)
1212{
1213 MachProcessSP procSP;
1214 if (GetProcessSP (pid, procSP))
1215 procSP->Events().ResetEvents(event_mask);
1216}
1217
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001218// Breakpoints
Greg Claytond8cf1a12013-06-12 00:46:38 +00001219nub_bool_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001220DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
1221{
1222 MachProcessSP procSP;
1223 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001224 return procSP->CreateBreakpoint(addr, size, hardware) != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001225 return false;
1226}
1227
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001228nub_bool_t
Greg Claytond8cf1a12013-06-12 00:46:38 +00001229DNBBreakpointClear (nub_process_t pid, nub_addr_t addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001230{
1231 MachProcessSP procSP;
1232 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001233 return procSP->DisableBreakpoint(addr, true);
1234 return false; // Failed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001235}
1236
Greg Claytond8cf1a12013-06-12 00:46:38 +00001237
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001238//----------------------------------------------------------------------
1239// Watchpoints
1240//----------------------------------------------------------------------
Greg Claytond8cf1a12013-06-12 00:46:38 +00001241nub_bool_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001242DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware)
1243{
1244 MachProcessSP procSP;
1245 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001246 return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001247 return false;
1248}
1249
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001250nub_bool_t
Greg Claytond8cf1a12013-06-12 00:46:38 +00001251DNBWatchpointClear (nub_process_t pid, nub_addr_t addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001252{
1253 MachProcessSP procSP;
1254 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001255 return procSP->DisableWatchpoint(addr, true);
1256 return false; // Failed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001257}
1258
1259//----------------------------------------------------------------------
Johnny Chen64637202012-05-23 21:09:52 +00001260// Return the number of supported hardware watchpoints.
1261//----------------------------------------------------------------------
1262uint32_t
1263DNBWatchpointGetNumSupportedHWP (nub_process_t pid)
1264{
1265 MachProcessSP procSP;
1266 if (GetProcessSP (pid, procSP))
1267 return procSP->GetNumSupportedHardwareWatchpoints();
1268 return 0;
1269}
1270
1271//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001272// Read memory in the address space of process PID. This call will take
1273// care of setting and restoring permissions and breaking up the memory
1274// read into multiple chunks as required.
1275//
1276// RETURNS: number of bytes actually read
1277//----------------------------------------------------------------------
1278nub_size_t
1279DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf)
1280{
1281 MachProcessSP procSP;
1282 if (GetProcessSP (pid, procSP))
1283 return procSP->ReadMemory(addr, size, buf);
1284 return 0;
1285}
1286
Greg Clayton0b90be12015-06-23 21:27:50 +00001287uint64_t
1288DNBProcessMemoryReadInteger (nub_process_t pid, nub_addr_t addr, nub_size_t integer_size, uint64_t fail_value)
1289{
1290 union Integers
1291 {
1292 uint8_t u8;
1293 uint16_t u16;
1294 uint32_t u32;
1295 uint64_t u64;
1296 };
1297
1298 if (integer_size <= sizeof(uint64_t))
1299 {
1300 Integers ints;
1301 if (DNBProcessMemoryRead(pid, addr, integer_size, &ints) == integer_size)
1302 {
1303 switch (integer_size)
1304 {
1305 case 1: return ints.u8;
1306 case 2: return ints.u16;
1307 case 3: return ints.u32 & 0xffffffu;
1308 case 4: return ints.u32;
1309 case 5: return ints.u32 & 0x000000ffffffffffull;
1310 case 6: return ints.u32 & 0x0000ffffffffffffull;
1311 case 7: return ints.u32 & 0x00ffffffffffffffull;
1312 case 8: return ints.u64;
1313 }
1314 }
1315 }
1316 return fail_value;
1317
1318}
1319
1320nub_addr_t
1321DNBProcessMemoryReadPointer (nub_process_t pid, nub_addr_t addr)
1322{
1323 cpu_type_t cputype = DNBProcessGetCPUType (pid);
1324 if (cputype)
1325 {
1326 const nub_size_t pointer_size = (cputype & CPU_ARCH_ABI64) ? 8 : 4;
1327 return DNBProcessMemoryReadInteger(pid, addr, pointer_size, 0);
1328 }
1329 return 0;
1330
1331}
1332
1333std::string
1334DNBProcessMemoryReadCString (nub_process_t pid, nub_addr_t addr)
1335{
1336 std::string cstr;
1337 char buffer[256];
1338 const nub_size_t max_buffer_cstr_length = sizeof(buffer)-1;
1339 buffer[max_buffer_cstr_length] = '\0';
1340 nub_size_t length = 0;
1341 nub_addr_t curr_addr = addr;
1342 do
1343 {
1344 nub_size_t bytes_read = DNBProcessMemoryRead(pid, curr_addr, max_buffer_cstr_length, buffer);
1345 if (bytes_read == 0)
1346 break;
1347 length = strlen(buffer);
1348 cstr.append(buffer, length);
1349 curr_addr += length;
1350 } while (length == max_buffer_cstr_length);
1351 return cstr;
1352}
1353
1354std::string
1355DNBProcessMemoryReadCStringFixed (nub_process_t pid, nub_addr_t addr, nub_size_t fixed_length)
1356{
1357 std::string cstr;
1358 char buffer[fixed_length+1];
1359 buffer[fixed_length] = '\0';
1360 nub_size_t bytes_read = DNBProcessMemoryRead(pid, addr, fixed_length, buffer);
1361 if (bytes_read > 0)
1362 cstr.assign(buffer);
1363 return cstr;
1364}
1365
1366
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001367//----------------------------------------------------------------------
1368// Write memory to the address space of process PID. This call will take
1369// care of setting and restoring permissions and breaking up the memory
1370// write into multiple chunks as required.
1371//
1372// RETURNS: number of bytes actually written
1373//----------------------------------------------------------------------
1374nub_size_t
1375DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf)
1376{
1377 MachProcessSP procSP;
1378 if (GetProcessSP (pid, procSP))
1379 return procSP->WriteMemory(addr, size, buf);
1380 return 0;
1381}
1382
1383nub_addr_t
1384DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions)
1385{
1386 MachProcessSP procSP;
1387 if (GetProcessSP (pid, procSP))
1388 return procSP->Task().AllocateMemory (size, permissions);
1389 return 0;
1390}
1391
1392nub_bool_t
1393DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr)
1394{
1395 MachProcessSP procSP;
1396 if (GetProcessSP (pid, procSP))
1397 return procSP->Task().DeallocateMemory (addr);
1398 return 0;
1399}
1400
Jason Molenda1f3966b2011-11-08 04:28:12 +00001401//----------------------------------------------------------------------
Jason Molenda3dc85832011-11-09 08:03:56 +00001402// Find attributes of the memory region that contains ADDR for process PID,
1403// if possible, and return a string describing those attributes.
Jason Molenda1f3966b2011-11-08 04:28:12 +00001404//
Jason Molenda3dc85832011-11-09 08:03:56 +00001405// Returns 1 if we could find attributes for this region and OUTBUF can
1406// be sent to the remote debugger.
Jason Molenda1f3966b2011-11-08 04:28:12 +00001407//
Jason Molenda3dc85832011-11-09 08:03:56 +00001408// Returns 0 if we couldn't find the attributes for a region of memory at
1409// that address and OUTBUF should not be sent.
1410//
1411// Returns -1 if this platform cannot look up information about memory regions
1412// or if we do not yet have a valid launched process.
1413//
Jason Molenda1f3966b2011-11-08 04:28:12 +00001414//----------------------------------------------------------------------
1415int
Greg Claytonfc5dd292011-12-12 18:51:14 +00001416DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info)
Jason Molenda1f3966b2011-11-08 04:28:12 +00001417{
1418 MachProcessSP procSP;
1419 if (GetProcessSP (pid, procSP))
Greg Clayton46fb5582011-11-18 07:03:08 +00001420 return procSP->Task().GetMemoryRegionInfo (addr, region_info);
1421
Jason Molenda1f3966b2011-11-08 04:28:12 +00001422 return -1;
1423}
1424
Han Ming Ong929a94f2012-11-29 22:14:45 +00001425std::string
Han Ming Ong8764fe72013-03-04 21:25:51 +00001426DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType)
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001427{
1428 MachProcessSP procSP;
1429 if (GetProcessSP (pid, procSP))
Han Ming Ong8764fe72013-03-04 21:25:51 +00001430 return procSP->Task().GetProfileData(scanType);
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001431
Han Ming Ong929a94f2012-11-29 22:14:45 +00001432 return std::string("");
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001433}
1434
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001435nub_bool_t
Han Ming Ong8764fe72013-03-04 21:25:51 +00001436DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001437{
1438 MachProcessSP procSP;
1439 if (GetProcessSP (pid, procSP))
1440 {
Han Ming Ong8764fe72013-03-04 21:25:51 +00001441 procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type);
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001442 return true;
1443 }
1444
1445 return false;
1446}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001447
1448//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001449// Get the number of threads for the specified process.
1450//----------------------------------------------------------------------
1451nub_size_t
1452DNBProcessGetNumThreads (nub_process_t pid)
1453{
1454 MachProcessSP procSP;
1455 if (GetProcessSP (pid, procSP))
1456 return procSP->GetNumThreads();
1457 return 0;
1458}
1459
1460//----------------------------------------------------------------------
1461// Get the thread ID of the current thread.
1462//----------------------------------------------------------------------
1463nub_thread_t
1464DNBProcessGetCurrentThread (nub_process_t pid)
1465{
1466 MachProcessSP procSP;
1467 if (GetProcessSP (pid, procSP))
1468 return procSP->GetCurrentThread();
1469 return 0;
1470}
1471
1472//----------------------------------------------------------------------
Jason Molendad5318c02013-04-03 04:18:47 +00001473// Get the mach port number of the current thread.
1474//----------------------------------------------------------------------
1475nub_thread_t
1476DNBProcessGetCurrentThreadMachPort (nub_process_t pid)
1477{
1478 MachProcessSP procSP;
1479 if (GetProcessSP (pid, procSP))
1480 return procSP->GetCurrentThreadMachPort();
1481 return 0;
1482}
1483
1484//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001485// Change the current thread.
1486//----------------------------------------------------------------------
1487nub_thread_t
1488DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid)
1489{
1490 MachProcessSP procSP;
1491 if (GetProcessSP (pid, procSP))
1492 return procSP->SetCurrentThread (tid);
1493 return INVALID_NUB_THREAD;
1494}
1495
1496
1497//----------------------------------------------------------------------
1498// Dump a string describing a thread's stop reason to the specified file
1499// handle
1500//----------------------------------------------------------------------
1501nub_bool_t
1502DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
1503{
1504 MachProcessSP procSP;
1505 if (GetProcessSP (pid, procSP))
1506 return procSP->GetThreadStoppedReason (tid, stop_info);
1507 return false;
1508}
1509
1510//----------------------------------------------------------------------
1511// Return string description for the specified thread.
1512//
1513// RETURNS: NULL if the thread isn't valid, else a NULL terminated C
1514// string from a static buffer that must be copied prior to subsequent
1515// calls.
1516//----------------------------------------------------------------------
1517const char *
1518DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid)
1519{
1520 MachProcessSP procSP;
1521 if (GetProcessSP (pid, procSP))
1522 return procSP->GetThreadInfo (tid);
1523 return NULL;
1524}
1525
1526//----------------------------------------------------------------------
1527// Get the thread ID given a thread index.
1528//----------------------------------------------------------------------
1529nub_thread_t
1530DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx)
1531{
1532 MachProcessSP procSP;
1533 if (GetProcessSP (pid, procSP))
1534 return procSP->GetThreadAtIndex (thread_idx);
1535 return INVALID_NUB_THREAD;
1536}
1537
Jim Ingham279ceec2012-07-25 21:12:43 +00001538//----------------------------------------------------------------------
1539// Do whatever is needed to sync the thread's register state with it's kernel values.
1540//----------------------------------------------------------------------
1541nub_bool_t
1542DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid)
1543{
1544 MachProcessSP procSP;
1545 if (GetProcessSP (pid, procSP))
1546 return procSP->SyncThreadState (tid);
1547 return false;
1548
1549}
1550
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001551nub_addr_t
1552DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid)
1553{
1554 MachProcessSP procSP;
1555 DNBError err;
1556 if (GetProcessSP (pid, procSP))
1557 return procSP->Task().GetDYLDAllImageInfosAddress (err);
1558 return INVALID_NUB_ADDRESS;
1559}
1560
1561
1562nub_bool_t
1563DNBProcessSharedLibrariesUpdated(nub_process_t pid)
1564{
1565 MachProcessSP procSP;
1566 if (GetProcessSP (pid, procSP))
1567 {
1568 procSP->SharedLibrariesUpdated ();
1569 return true;
1570 }
1571 return false;
1572}
1573
1574//----------------------------------------------------------------------
1575// Get the current shared library information for a process. Only return
1576// the shared libraries that have changed since the last shared library
1577// state changed event if only_changed is non-zero.
1578//----------------------------------------------------------------------
1579nub_size_t
1580DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos)
1581{
1582 MachProcessSP procSP;
1583 if (GetProcessSP (pid, procSP))
1584 return procSP->CopyImageInfos (image_infos, only_changed);
1585
1586 // If we have no process, then return NULL for the shared library info
1587 // and zero for shared library count
1588 *image_infos = NULL;
1589 return 0;
1590}
1591
Greg Claytond04f0ed2015-05-26 18:00:51 +00001592uint32_t
1593DNBGetRegisterCPUType()
1594{
1595 return DNBArchProtocol::GetRegisterCPUType ();
1596
1597}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001598//----------------------------------------------------------------------
1599// Get the register set information for a specific thread.
1600//----------------------------------------------------------------------
1601const DNBRegisterSetInfo *
1602DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
1603{
Greg Clayton3af9ea52010-11-18 05:57:03 +00001604 return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001605}
1606
1607
1608//----------------------------------------------------------------------
1609// Read a register value by register set and register index.
1610//----------------------------------------------------------------------
1611nub_bool_t
1612DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value)
1613{
1614 MachProcessSP procSP;
1615 ::bzero (value, sizeof(DNBRegisterValue));
1616 if (GetProcessSP (pid, procSP))
1617 {
1618 if (tid != INVALID_NUB_THREAD)
1619 return procSP->GetRegisterValue (tid, set, reg, value);
1620 }
1621 return false;
1622}
1623
1624nub_bool_t
1625DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value)
1626{
1627 if (tid != INVALID_NUB_THREAD)
1628 {
1629 MachProcessSP procSP;
1630 if (GetProcessSP (pid, procSP))
1631 return procSP->SetRegisterValue (tid, set, reg, value);
1632 }
1633 return false;
1634}
1635
1636nub_size_t
1637DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len)
1638{
1639 MachProcessSP procSP;
1640 if (GetProcessSP (pid, procSP))
1641 {
1642 if (tid != INVALID_NUB_THREAD)
1643 return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len);
1644 }
1645 ::bzero (buf, buf_len);
1646 return 0;
1647
1648}
1649
1650nub_size_t
1651DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len)
1652{
1653 MachProcessSP procSP;
1654 if (GetProcessSP (pid, procSP))
1655 {
1656 if (tid != INVALID_NUB_THREAD)
1657 return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len);
1658 }
1659 return 0;
1660}
1661
Greg Claytonf74cf862013-11-13 23:28:31 +00001662uint32_t
1663DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid)
1664{
1665 if (tid != INVALID_NUB_THREAD)
1666 {
1667 MachProcessSP procSP;
1668 if (GetProcessSP (pid, procSP))
1669 return procSP->GetThreadList().SaveRegisterState (tid);
1670 }
1671 return 0;
1672}
1673nub_bool_t
1674DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id)
1675{
1676 if (tid != INVALID_NUB_THREAD)
1677 {
1678 MachProcessSP procSP;
1679 if (GetProcessSP (pid, procSP))
1680 return procSP->GetThreadList().RestoreRegisterState (tid, save_id);
1681 }
1682 return false;
1683}
1684
1685
1686
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001687//----------------------------------------------------------------------
1688// Read a register value by name.
1689//----------------------------------------------------------------------
1690nub_bool_t
1691DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value)
1692{
1693 MachProcessSP procSP;
1694 ::bzero (value, sizeof(DNBRegisterValue));
1695 if (GetProcessSP (pid, procSP))
1696 {
1697 const struct DNBRegisterSetInfo *set_info;
1698 nub_size_t num_reg_sets = 0;
1699 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1700 if (set_info)
1701 {
1702 uint32_t set = reg_set;
1703 uint32_t reg;
1704 if (set == REGISTER_SET_ALL)
1705 {
1706 for (set = 1; set < num_reg_sets; ++set)
1707 {
1708 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1709 {
1710 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1711 return procSP->GetRegisterValue (tid, set, reg, value);
1712 }
1713 }
1714 }
1715 else
1716 {
1717 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1718 {
1719 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1720 return procSP->GetRegisterValue (tid, set, reg, value);
1721 }
1722 }
1723 }
1724 }
1725 return false;
1726}
1727
1728
1729//----------------------------------------------------------------------
1730// Read a register set and register number from the register name.
1731//----------------------------------------------------------------------
1732nub_bool_t
1733DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info)
1734{
1735 const struct DNBRegisterSetInfo *set_info;
1736 nub_size_t num_reg_sets = 0;
1737 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1738 if (set_info)
1739 {
1740 uint32_t set, reg;
1741 for (set = 1; set < num_reg_sets; ++set)
1742 {
1743 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1744 {
1745 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1746 {
1747 *info = set_info[set].registers[reg];
1748 return true;
1749 }
1750 }
1751 }
1752
1753 for (set = 1; set < num_reg_sets; ++set)
1754 {
1755 uint32_t reg;
1756 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1757 {
1758 if (set_info[set].registers[reg].alt == NULL)
1759 continue;
1760
1761 if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0)
1762 {
1763 *info = set_info[set].registers[reg];
1764 return true;
1765 }
1766 }
1767 }
1768 }
1769
1770 ::bzero (info, sizeof(DNBRegisterInfo));
1771 return false;
1772}
1773
1774
1775//----------------------------------------------------------------------
1776// Set the name to address callback function that this nub can use
1777// for any name to address lookups that are needed.
1778//----------------------------------------------------------------------
1779nub_bool_t
1780DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton)
1781{
1782 MachProcessSP procSP;
1783 if (GetProcessSP (pid, procSP))
1784 {
1785 procSP->SetNameToAddressCallback (callback, baton);
1786 return true;
1787 }
1788 return false;
1789}
1790
1791
1792//----------------------------------------------------------------------
1793// Set the name to address callback function that this nub can use
1794// for any name to address lookups that are needed.
1795//----------------------------------------------------------------------
1796nub_bool_t
1797DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton)
1798{
1799 MachProcessSP procSP;
1800 if (GetProcessSP (pid, procSP))
1801 {
1802 procSP->SetSharedLibraryInfoCallback (callback, baton);
1803 return true;
1804 }
1805 return false;
1806}
1807
1808nub_addr_t
1809DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib)
1810{
1811 MachProcessSP procSP;
1812 if (GetProcessSP (pid, procSP))
1813 {
1814 return procSP->LookupSymbol (name, shlib);
1815 }
1816 return INVALID_NUB_ADDRESS;
1817}
1818
1819
1820nub_size_t
1821DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size)
1822{
1823 MachProcessSP procSP;
1824 if (GetProcessSP (pid, procSP))
1825 return procSP->GetAvailableSTDOUT (buf, buf_size);
1826 return 0;
1827}
1828
1829nub_size_t
1830DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size)
1831{
1832 MachProcessSP procSP;
1833 if (GetProcessSP (pid, procSP))
1834 return procSP->GetAvailableSTDERR (buf, buf_size);
1835 return 0;
1836}
1837
1838nub_size_t
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001839DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size)
1840{
1841 MachProcessSP procSP;
1842 if (GetProcessSP (pid, procSP))
1843 return procSP->GetAsyncProfileData (buf, buf_size);
1844 return 0;
1845}
1846
1847nub_size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001848DNBProcessGetStopCount (nub_process_t pid)
1849{
1850 MachProcessSP procSP;
1851 if (GetProcessSP (pid, procSP))
1852 return procSP->StopCount();
1853 return 0;
1854}
1855
Greg Clayton71337622011-02-24 22:24:29 +00001856uint32_t
1857DNBProcessGetCPUType (nub_process_t pid)
1858{
1859 MachProcessSP procSP;
1860 if (GetProcessSP (pid, procSP))
1861 return procSP->GetCPUType ();
1862 return 0;
1863
1864}
1865
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001866nub_bool_t
1867DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
1868{
1869 if (path == NULL || path[0] == '\0')
1870 return false;
1871
1872 char max_path[PATH_MAX];
1873 std::string result;
1874 CFString::GlobPath(path, result);
1875
1876 if (result.empty())
1877 result = path;
Greg Clayton48baf7a2012-10-31 21:44:39 +00001878
1879 struct stat path_stat;
1880 if (::stat(path, &path_stat) == 0)
1881 {
1882 if ((path_stat.st_mode & S_IFMT) == S_IFDIR)
1883 {
1884 CFBundle bundle (path);
1885 CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
1886 if (url.get())
1887 {
1888 if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size))
1889 return true;
1890 }
1891 }
1892 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001893
1894 if (realpath(path, max_path))
1895 {
1896 // Found the path relatively...
1897 ::strncpy(resolved_path, max_path, resolved_path_size);
1898 return strlen(resolved_path) + 1 < resolved_path_size;
1899 }
1900 else
1901 {
1902 // Not a relative path, check the PATH environment variable if the
1903 const char *PATH = getenv("PATH");
1904 if (PATH)
1905 {
1906 const char *curr_path_start = PATH;
1907 const char *curr_path_end;
1908 while (curr_path_start && *curr_path_start)
1909 {
1910 curr_path_end = strchr(curr_path_start, ':');
1911 if (curr_path_end == NULL)
1912 {
1913 result.assign(curr_path_start);
1914 curr_path_start = NULL;
1915 }
1916 else if (curr_path_end > curr_path_start)
1917 {
1918 size_t len = curr_path_end - curr_path_start;
1919 result.assign(curr_path_start, len);
1920 curr_path_start += len + 1;
1921 }
1922 else
1923 break;
1924
1925 result += '/';
1926 result += path;
1927 struct stat s;
1928 if (stat(result.c_str(), &s) == 0)
1929 {
1930 ::strncpy(resolved_path, result.c_str(), resolved_path_size);
1931 return result.size() + 1 < resolved_path_size;
1932 }
1933 }
1934 }
1935 }
1936 return false;
1937}
1938
Jason Molenda6acc86c2015-08-12 03:27:33 +00001939bool
1940DNBGetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch)
1941{
1942 return MachProcess::GetOSVersionNumbers (major, minor, patch);
1943}
1944
Greg Clayton3af9ea52010-11-18 05:57:03 +00001945
1946void
1947DNBInitialize()
1948{
1949 DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
1950#if defined (__i386__) || defined (__x86_64__)
1951 DNBArchImplI386::Initialize();
1952 DNBArchImplX86_64::Initialize();
Todd Fiala013434e2014-07-09 01:29:05 +00001953#elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
Greg Clayton3af9ea52010-11-18 05:57:03 +00001954 DNBArchMachARM::Initialize();
Jason Molendaa3329782014-03-29 18:54:20 +00001955 DNBArchMachARM64::Initialize();
Greg Clayton3af9ea52010-11-18 05:57:03 +00001956#endif
1957}
1958
1959void
1960DNBTerminate()
1961{
1962}
Greg Clayton3c144382010-12-01 22:45:40 +00001963
1964nub_bool_t
1965DNBSetArchitecture (const char *arch)
1966{
1967 if (arch && arch[0])
1968 {
1969 if (strcasecmp (arch, "i386") == 0)
1970 return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386);
Greg Claytona86dc432014-01-22 23:42:03 +00001971 else if ((strcasecmp (arch, "x86_64") == 0) || (strcasecmp (arch, "x86_64h") == 0))
Greg Clayton3c144382010-12-01 22:45:40 +00001972 return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64);
Todd Fiala013434e2014-07-09 01:29:05 +00001973 else if (strstr (arch, "arm64") == arch || strstr (arch, "armv8") == arch || strstr (arch, "aarch64") == arch)
Jason Molendaa3329782014-03-29 18:54:20 +00001974 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM64);
Greg Clayton3c144382010-12-01 22:45:40 +00001975 else if (strstr (arch, "arm") == arch)
1976 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM);
1977 }
1978 return false;
1979}