blob: bb360364919942821856cb87226a6daed0de6340 [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{
Saleem Abdulrasoolbd7ecf42016-05-06 17:32:58 +0000363 DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, working_dir=%s, stdin=%s, stdout=%s, "
364 "stderr=%s, no-stdio=%i, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = "
365 "%llu) called...",
366 __FUNCTION__, path, static_cast<void *>(argv), static_cast<void *>(envp), working_directory,
367 stdin_path, stdout_path, stderr_path, no_stdio, launch_flavor, disable_aslr,
368 static_cast<void *>(err_str), static_cast<uint64_t>(err_len));
369
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000370 if (err_str && err_len > 0)
371 err_str[0] = '\0';
372 struct stat path_stat;
373 if (::stat(path, &path_stat) == -1)
374 {
375 char stat_error[256];
376 ::strerror_r (errno, stat_error, sizeof(stat_error));
377 snprintf(err_str, err_len, "%s (%s)", stat_error, path);
378 return INVALID_NUB_PROCESS;
379 }
380
381 MachProcessSP processSP (new MachProcess);
382 if (processSP.get())
383 {
384 DNBError launch_err;
Greg Clayton6779606a2011-01-22 23:43:18 +0000385 pid_t pid = processSP->LaunchForDebug (path,
386 argv,
387 envp,
388 working_directory,
389 stdin_path,
390 stdout_path,
391 stderr_path,
392 no_stdio,
393 launch_flavor,
Jason Molendaa3329782014-03-29 18:54:20 +0000394 disable_aslr,
395 event_data,
Greg Clayton6779606a2011-01-22 23:43:18 +0000396 launch_err);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397 if (err_str)
398 {
399 *err_str = '\0';
400 if (launch_err.Fail())
401 {
402 const char *launch_err_str = launch_err.AsString();
403 if (launch_err_str)
404 {
405 strncpy(err_str, launch_err_str, err_len-1);
406 err_str[err_len-1] = '\0'; // Make sure the error string is terminated
407 }
408 }
409 }
410
411 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
412
413 if (pid != INVALID_NUB_PROCESS)
414 {
415 // Spawn a thread to reap our child inferior process...
416 spawn_waitpid_thread (pid);
417
418 if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL)
419 {
420 // We failed to get the task for our process ID which is bad.
Greg Claytonfb640c22012-02-02 19:23:22 +0000421 // Kill our process otherwise it will be stopped at the entry
422 // point and get reparented to someone else and never go away.
Jason Molenda153c8e02013-01-05 06:08:51 +0000423 DNBLog ("Could not get task port for process, sending SIGKILL and exiting.");
Greg Claytonfb640c22012-02-02 19:23:22 +0000424 kill (SIGKILL, pid);
425
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000426 if (err_str && err_len > 0)
427 {
428 if (launch_err.AsString())
429 {
430 ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString());
431 }
432 else
433 {
434 ::snprintf (err_str, err_len, "failed to get the task for process %i", pid);
435 }
436 }
437 }
438 else
439 {
Charles Davisb786e7d2012-02-21 00:53:12 +0000440 bool res = AddProcessToMap(pid, processSP);
Bruce Mitchener8a67bf72015-07-24 00:23:29 +0000441 UNUSED_IF_ASSERT_DISABLED(res);
Charles Davisb786e7d2012-02-21 00:53:12 +0000442 assert(res && "Couldn't add process to map!");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000443 return pid;
444 }
445 }
446 }
447 return INVALID_NUB_PROCESS;
448}
449
Jason Molenda752e1e82015-07-29 01:42:16 +0000450// If there is one process with a given name, return the pid for that process.
451nub_process_t
452DNBProcessGetPIDByName (const char *name)
453{
454 std::vector<struct kinfo_proc> matching_proc_infos;
455 size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
456 if (num_matching_proc_infos == 1)
457 {
458 return matching_proc_infos[0].kp_proc.p_pid;
459 }
460 return INVALID_NUB_PROCESS;
461}
462
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000463nub_process_t
464DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
465{
466 if (err_str && err_len > 0)
467 err_str[0] = '\0';
468 std::vector<struct kinfo_proc> matching_proc_infos;
469 size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
470 if (num_matching_proc_infos == 0)
471 {
472 DNBLogError ("error: no processes match '%s'\n", name);
473 return INVALID_NUB_PROCESS;
474 }
475 else if (num_matching_proc_infos > 1)
476 {
Greg Clayton43e0af02012-09-18 18:04:04 +0000477 DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000478 size_t i;
479 for (i=0; i<num_matching_proc_infos; ++i)
480 DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
481 return INVALID_NUB_PROCESS;
482 }
Greg Clayton3af9ea52010-11-18 05:57:03 +0000483
484 return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000485}
486
487nub_process_t
488DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len)
489{
490 if (err_str && err_len > 0)
491 err_str[0] = '\0';
492
Johnny Chen64503c82011-08-11 19:03:44 +0000493 pid_t pid = INVALID_NUB_PROCESS;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000494 MachProcessSP processSP(new MachProcess);
495 if (processSP.get())
496 {
497 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid);
498 pid = processSP->AttachForDebug (attach_pid, err_str, err_len);
499
500 if (pid != INVALID_NUB_PROCESS)
501 {
Charles Davisb786e7d2012-02-21 00:53:12 +0000502 bool res = AddProcessToMap(pid, processSP);
Bruce Mitchener8a67bf72015-07-24 00:23:29 +0000503 UNUSED_IF_ASSERT_DISABLED(res);
Charles Davisb786e7d2012-02-21 00:53:12 +0000504 assert(res && "Couldn't add process to map!");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000505 spawn_waitpid_thread(pid);
506 }
507 }
508
509 while (pid != INVALID_NUB_PROCESS)
510 {
511 // Wait for process to start up and hit entry point
Greg Clayton3af9ea52010-11-18 05:57:03 +0000512 DNBLogThreadedIf (LOG_PROCESS,
513 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
514 __FUNCTION__,
515 pid);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000516 nub_event_t set_events = DNBProcessWaitForEvents (pid,
Greg Clayton3af9ea52010-11-18 05:57:03 +0000517 eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
518 true,
519 timeout);
520
521 DNBLogThreadedIf (LOG_PROCESS,
522 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
523 __FUNCTION__,
524 pid,
525 set_events);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000526
527 if (set_events == 0)
528 {
529 if (err_str && err_len > 0)
530 snprintf(err_str, err_len, "operation timed out");
531 pid = INVALID_NUB_PROCESS;
532 }
533 else
534 {
535 if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
536 {
537 nub_state_t pid_state = DNBProcessGetState (pid);
538 DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s",
539 __FUNCTION__, pid, DNBStateAsString(pid_state));
540
541 switch (pid_state)
542 {
Greg Clayton3af9ea52010-11-18 05:57:03 +0000543 case eStateInvalid:
544 case eStateUnloaded:
545 case eStateAttaching:
546 case eStateLaunching:
547 case eStateSuspended:
548 break; // Ignore
549
550 case eStateRunning:
551 case eStateStepping:
552 // Still waiting to stop at entry point...
553 break;
554
555 case eStateStopped:
556 case eStateCrashed:
557 return pid;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000558
Greg Clayton3af9ea52010-11-18 05:57:03 +0000559 case eStateDetached:
560 case eStateExited:
561 if (err_str && err_len > 0)
562 snprintf(err_str, err_len, "process exited");
563 return INVALID_NUB_PROCESS;
564 }
565 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000566
567 DNBProcessResetEvents(pid, set_events);
568 }
569 }
570
571 return INVALID_NUB_PROCESS;
572}
573
Greg Clayton9eb4e032012-11-06 23:36:26 +0000574size_t
Greg Clayton3af9ea52010-11-18 05:57:03 +0000575GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000576{
Greg Clayton9eb4e032012-11-06 23:36:26 +0000577 size_t size = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000578 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
Jim Inghamc1fdb882014-06-27 16:02:55 +0000579 u_int namelen = sizeof(name)/sizeof(int);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000580 int err;
581
582 // Try to find out how many processes are around so we can
583 // size the buffer appropriately. sysctl's man page specifically suggests
584 // this approach, and says it returns a bit larger size than needed to
585 // handle any new processes created between then and now.
586
587 err = ::sysctl (name, namelen, NULL, &size, NULL, 0);
588
589 if ((err < 0) && (err != ENOMEM))
590 {
591 proc_infos.clear();
592 perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
593 return 0;
594 }
595
596
597 // Increase the size of the buffer by a few processes in case more have
598 // been spawned
599 proc_infos.resize (size / sizeof(struct kinfo_proc));
600 size = proc_infos.size() * sizeof(struct kinfo_proc); // Make sure we don't exceed our resize...
601 err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0);
602 if (err < 0)
603 {
604 proc_infos.clear();
605 return 0;
606 }
607
608 // Trim down our array to fit what we actually got back
609 proc_infos.resize(size / sizeof(struct kinfo_proc));
610 return proc_infos.size();
611}
612
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000613static size_t
614GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos)
615{
616
617 matching_proc_infos.clear();
618 if (full_process_name && full_process_name[0])
619 {
620 // We only get the process name, not the full path, from the proc_info. So just take the
621 // base name of the process name...
622 const char *process_name;
623 process_name = strrchr (full_process_name, '/');
624 if (process_name == NULL)
Greg Clayton7dab2be2012-07-19 02:45:35 +0000625 process_name = full_process_name;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000626 else
Greg Clayton7dab2be2012-07-19 02:45:35 +0000627 process_name++;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000628
Greg Claytonee2ed522015-03-09 19:45:23 +0000629 const size_t process_name_len = strlen(process_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000630 std::vector<struct kinfo_proc> proc_infos;
631 const size_t num_proc_infos = GetAllInfos(proc_infos);
632 if (num_proc_infos > 0)
633 {
634 uint32_t i;
635 for (i=0; i<num_proc_infos; i++)
636 {
637 // Skip zombie processes and processes with unset status
638 if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB)
639 continue;
640
641 // Check for process by name. We only check the first MAXCOMLEN
642 // chars as that is all that kp_proc.p_comm holds.
Jim Ingham490bccd2012-11-01 01:04:46 +0000643
Greg Clayton7dab2be2012-07-19 02:45:35 +0000644 if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000645 {
Greg Clayton7dab2be2012-07-19 02:45:35 +0000646 if (process_name_len > MAXCOMLEN)
647 {
648 // We found a matching process name whose first MAXCOMLEN
649 // characters match, but there is more to the name than
Jim Ingham490bccd2012-11-01 01:04:46 +0000650 // this. We need to get the full process name. Use proc_pidpath, which will get
651 // us the full path to the executed process.
Greg Clayton7dab2be2012-07-19 02:45:35 +0000652
Jim Ingham490bccd2012-11-01 01:04:46 +0000653 char proc_path_buf[PATH_MAX];
Greg Clayton7dab2be2012-07-19 02:45:35 +0000654
Jim Ingham490bccd2012-11-01 01:04:46 +0000655 int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX);
656 if (return_val > 0)
Greg Clayton7dab2be2012-07-19 02:45:35 +0000657 {
Jim Ingham490bccd2012-11-01 01:04:46 +0000658 // Okay, now search backwards from that to see if there is a
659 // slash in the name. Note, even though we got all the args we don't care
660 // because the list data is just a bunch of concatenated null terminated strings
661 // so strrchr will start from the end of argv0.
662
663 const char *argv_basename = strrchr(proc_path_buf, '/');
Greg Clayton7dab2be2012-07-19 02:45:35 +0000664 if (argv_basename)
665 {
666 // Skip the '/'
667 ++argv_basename;
668 }
669 else
670 {
671 // 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 +0000672 argv_basename = proc_path_buf;
Greg Clayton7dab2be2012-07-19 02:45:35 +0000673 }
674
675 if (argv_basename)
676 {
677 if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0)
678 {
679 matching_proc_infos.push_back(proc_infos[i]);
680 }
681 }
682 }
683 }
684 else
685 {
686 // We found a matching process, add it to our list
Greg Clayton7dab2be2012-07-19 02:45:35 +0000687 matching_proc_infos.push_back(proc_infos[i]);
688 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000689 }
690 }
691 }
692 }
693 // return the newly added matches.
694 return matching_proc_infos.size();
695}
696
697nub_process_t
Greg Clayton19388cf2010-10-18 01:45:30 +0000698DNBProcessAttachWait (const char *waitfor_process_name,
699 nub_launch_flavor_t launch_flavor,
Jim Inghamcd16df92012-07-20 21:37:13 +0000700 bool ignore_existing,
Greg Clayton19388cf2010-10-18 01:45:30 +0000701 struct timespec *timeout_abstime,
702 useconds_t waitfor_interval,
703 char *err_str,
704 size_t err_len,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000705 DNBShouldCancelCallback should_cancel_callback,
706 void *callback_data)
707{
708 DNBError prepare_error;
709 std::vector<struct kinfo_proc> exclude_proc_infos;
710 size_t num_exclude_proc_infos;
711
712 // If the PrepareForAttach returns a valid token, use MachProcess to check
713 // for the process, otherwise scan the process table.
714
715 const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error);
716
717 if (prepare_error.Fail())
718 {
719 DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString());
720 return INVALID_NUB_PROCESS;
721 }
722
723 if (attach_token == NULL)
Jim Inghamcd16df92012-07-20 21:37:13 +0000724 {
725 if (ignore_existing)
726 num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
727 else
728 num_exclude_proc_infos = 0;
729 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000730
731 DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
732
733 // Loop and try to find the process by name
734 nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
735
736 while (waitfor_pid == INVALID_NUB_PROCESS)
737 {
738 if (attach_token != NULL)
739 {
740 nub_process_t pid;
Jason Molendac611a742015-10-23 02:49:51 +0000741 pid = MachProcess::CheckForProcess(attach_token, launch_flavor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000742 if (pid != INVALID_NUB_PROCESS)
743 {
744 waitfor_pid = pid;
745 break;
746 }
747 }
748 else
749 {
750
751 // Get the current process list, and check for matches that
752 // aren't in our original list. If anyone wants to attach
753 // to an existing process by name, they should do it with
754 // --attach=PROCNAME. Else we will wait for the first matching
755 // process that wasn't in our exclusion list.
756 std::vector<struct kinfo_proc> proc_infos;
757 const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos);
758 for (size_t i=0; i<num_proc_infos; i++)
759 {
760 nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
761 for (size_t j=0; j<num_exclude_proc_infos; j++)
762 {
763 if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid)
764 {
765 // This process was in our exclusion list, don't use it.
766 curr_pid = INVALID_NUB_PROCESS;
767 break;
768 }
769 }
770
771 // If we didn't find CURR_PID in our exclusion list, then use it.
772 if (curr_pid != INVALID_NUB_PROCESS)
773 {
774 // We found our process!
775 waitfor_pid = curr_pid;
776 break;
777 }
778 }
779 }
780
781 // If we haven't found our process yet, check for a timeout
782 // and then sleep for a bit until we poll again.
783 if (waitfor_pid == INVALID_NUB_PROCESS)
784 {
785 if (timeout_abstime != NULL)
786 {
787 // Check to see if we have a waitfor-duration option that
788 // has timed out?
789 if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime))
790 {
791 if (err_str && err_len > 0)
792 snprintf(err_str, err_len, "operation timed out");
793 DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name);
794 return INVALID_NUB_PROCESS;
795 }
796 }
797
798 // Call the should cancel callback as well...
799
800 if (should_cancel_callback != NULL
801 && should_cancel_callback (callback_data))
802 {
803 DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback.");
804 waitfor_pid = INVALID_NUB_PROCESS;
805 break;
806 }
807
808 ::usleep (waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again
809 }
810 }
811
812 if (waitfor_pid != INVALID_NUB_PROCESS)
813 {
814 DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid);
815 waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len);
816 }
817
818 bool success = waitfor_pid != INVALID_NUB_PROCESS;
Jason Molendac611a742015-10-23 02:49:51 +0000819 MachProcess::CleanupAfterAttach (attach_token, launch_flavor, success, prepare_error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000820
821 return waitfor_pid;
822}
823
824nub_bool_t
825DNBProcessDetach (nub_process_t pid)
826{
827 MachProcessSP procSP;
828 if (GetProcessSP (pid, procSP))
829 {
Jim Ingham58813182014-02-25 04:53:13 +0000830 const bool remove = true;
831 DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid);
832 procSP->DisableAllBreakpoints(remove);
833 procSP->DisableAllWatchpoints (remove);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000834 return procSP->Detach();
835 }
836 return false;
837}
838
839nub_bool_t
840DNBProcessKill (nub_process_t pid)
841{
842 MachProcessSP procSP;
843 if (GetProcessSP (pid, procSP))
844 {
845 return procSP->Kill ();
846 }
847 return false;
848}
849
850nub_bool_t
851DNBProcessSignal (nub_process_t pid, int signal)
852{
853 MachProcessSP procSP;
854 if (GetProcessSP (pid, procSP))
855 {
856 return procSP->Signal (signal);
857 }
858 return false;
859}
860
Greg Clayton4296c222014-04-24 19:54:32 +0000861
862nub_bool_t
863DNBProcessInterrupt(nub_process_t pid)
864{
865 MachProcessSP procSP;
866 if (GetProcessSP (pid, procSP))
867 return procSP->Interrupt();
868 return false;
869}
870
Jason Molendaa3329782014-03-29 18:54:20 +0000871nub_bool_t
872DNBProcessSendEvent (nub_process_t pid, const char *event)
873{
874 MachProcessSP procSP;
875 if (GetProcessSP (pid, procSP))
876 {
877 // FIXME: Do something with the error...
878 DNBError send_error;
879 return procSP->SendEvent (event, send_error);
880 }
881 return false;
882}
883
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000884
885nub_bool_t
886DNBProcessIsAlive (nub_process_t pid)
887{
888 MachProcessSP procSP;
889 if (GetProcessSP (pid, procSP))
890 {
891 return MachTask::IsValid (procSP->Task().TaskPort());
892 }
893 return eStateInvalid;
894}
895
896//----------------------------------------------------------------------
897// Process and Thread state information
898//----------------------------------------------------------------------
899nub_state_t
900DNBProcessGetState (nub_process_t pid)
901{
902 MachProcessSP procSP;
903 if (GetProcessSP (pid, procSP))
904 {
905 return procSP->GetState();
906 }
907 return eStateInvalid;
908}
909
910//----------------------------------------------------------------------
911// Process and Thread state information
912//----------------------------------------------------------------------
913nub_bool_t
914DNBProcessGetExitStatus (nub_process_t pid, int* status)
915{
916 MachProcessSP procSP;
917 if (GetProcessSP (pid, procSP))
918 {
919 return procSP->GetExitStatus(status);
920 }
921 return false;
922}
923
924nub_bool_t
925DNBProcessSetExitStatus (nub_process_t pid, int status)
926{
927 MachProcessSP procSP;
928 if (GetProcessSP (pid, procSP))
929 {
930 procSP->SetExitStatus(status);
931 return true;
932 }
933 return false;
934}
935
Jason Molendaa3329782014-03-29 18:54:20 +0000936const char *
937DNBProcessGetExitInfo (nub_process_t pid)
938{
939 MachProcessSP procSP;
940 if (GetProcessSP (pid, procSP))
941 {
942 return procSP->GetExitInfo();
943 }
944 return NULL;
945}
946
947nub_bool_t
948DNBProcessSetExitInfo (nub_process_t pid, const char *info)
949{
950 MachProcessSP procSP;
951 if (GetProcessSP (pid, procSP))
952 {
953 procSP->SetExitInfo(info);
954 return true;
955 }
956 return false;
957}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000958
959const char *
960DNBThreadGetName (nub_process_t pid, nub_thread_t tid)
961{
962 MachProcessSP procSP;
963 if (GetProcessSP (pid, procSP))
964 return procSP->ThreadGetName(tid);
965 return NULL;
966}
967
968
969nub_bool_t
970DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info)
971{
972 MachProcessSP procSP;
973 if (GetProcessSP (pid, procSP))
974 return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
975 return false;
976}
977
978nub_state_t
979DNBThreadGetState (nub_process_t pid, nub_thread_t tid)
980{
981 MachProcessSP procSP;
982 if (GetProcessSP (pid, procSP))
983 {
984 return procSP->ThreadGetState(tid);
985 }
986 return eStateInvalid;
987}
988
989const char *
990DNBStateAsString(nub_state_t state)
991{
992 switch (state)
993 {
Greg Claytoneffe5c92011-05-03 22:09:39 +0000994 case eStateInvalid: return "Invalid";
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000995 case eStateUnloaded: return "Unloaded";
996 case eStateAttaching: return "Attaching";
997 case eStateLaunching: return "Launching";
998 case eStateStopped: return "Stopped";
999 case eStateRunning: return "Running";
1000 case eStateStepping: return "Stepping";
1001 case eStateCrashed: return "Crashed";
1002 case eStateDetached: return "Detached";
1003 case eStateExited: return "Exited";
1004 case eStateSuspended: return "Suspended";
1005 }
1006 return "nub_state_t ???";
1007}
1008
Jason Molenda705b1802014-06-13 02:37:02 +00001009Genealogy::ThreadActivitySP
1010DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out)
1011{
1012 Genealogy::ThreadActivitySP thread_activity_sp;
1013 MachProcessSP procSP;
1014 if (GetProcessSP (pid, procSP))
1015 thread_activity_sp = procSP->GetGenealogyInfoForThread (tid, timed_out);
1016 return thread_activity_sp;
1017}
1018
1019Genealogy::ProcessExecutableInfoSP
1020DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx)
1021{
1022 Genealogy::ProcessExecutableInfoSP image_info_sp;
1023 MachProcessSP procSP;
1024 if (GetProcessSP (pid, procSP))
1025 {
1026 image_info_sp = procSP->GetGenealogyImageInfo (idx);
1027 }
1028 return image_info_sp;
1029}
1030
1031ThreadInfo::QoS
1032DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index)
1033{
1034 MachProcessSP procSP;
1035 if (GetProcessSP (pid, procSP))
1036 {
1037 return procSP->GetRequestedQoS (tid, tsd, dti_qos_class_index);
1038 }
1039 return ThreadInfo::QoS();
1040}
1041
1042nub_addr_t
1043DNBGetPThreadT (nub_process_t pid, nub_thread_t tid)
1044{
1045 MachProcessSP procSP;
1046 if (GetProcessSP (pid, procSP))
1047 {
1048 return procSP->GetPThreadT (tid);
1049 }
1050 return INVALID_NUB_ADDRESS;
1051}
1052
1053nub_addr_t
1054DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid)
1055{
1056 MachProcessSP procSP;
1057 if (GetProcessSP (pid, procSP))
1058 {
1059 return procSP->GetDispatchQueueT (tid);
1060 }
1061 return INVALID_NUB_ADDRESS;
1062}
1063
1064nub_addr_t
1065DNBGetTSDAddressForThread (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)
1066{
1067 MachProcessSP procSP;
1068 if (GetProcessSP (pid, procSP))
1069 {
1070 return procSP->GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
1071 }
1072 return INVALID_NUB_ADDRESS;
1073}
1074
Jason Molenda20ee21b2015-07-10 23:15:22 +00001075JSONGenerator::ObjectSP
1076DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count)
1077{
1078 MachProcessSP procSP;
1079 if (GetProcessSP (pid, procSP))
1080 {
1081 return procSP->GetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count);
1082 }
1083 return JSONGenerator::ObjectSP();
1084}
1085
Jason Molendaa2992312016-07-07 01:09:23 +00001086JSONGenerator::ObjectSP
1087DNBGetAllLoadedLibrariesInfos (nub_process_t pid)
1088{
1089 MachProcessSP procSP;
1090 if (GetProcessSP (pid, procSP))
1091 {
1092 return procSP->GetAllLoadedLibrariesInfos (pid);
1093 }
1094 return JSONGenerator::ObjectSP();
1095}
1096
1097JSONGenerator::ObjectSP
1098DNBGetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses)
1099{
1100 MachProcessSP procSP;
1101 if (GetProcessSP (pid, procSP))
1102 {
1103 return procSP->GetLibrariesInfoForAddresses (pid, macho_addresses);
1104 }
1105 return JSONGenerator::ObjectSP();
1106}
1107
1108JSONGenerator::ObjectSP
1109DNBGetSharedCacheInfo (nub_process_t pid)
1110{
1111 MachProcessSP procSP;
1112 if (GetProcessSP (pid, procSP))
1113 {
1114 return procSP->GetSharedCacheInfo (pid);
1115 }
1116 return JSONGenerator::ObjectSP();
1117}
1118
Jason Molenda20ee21b2015-07-10 23:15:22 +00001119
Jason Molenda705b1802014-06-13 02:37:02 +00001120
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001121const char *
1122DNBProcessGetExecutablePath (nub_process_t pid)
1123{
1124 MachProcessSP procSP;
1125 if (GetProcessSP (pid, procSP))
1126 {
1127 return procSP->Path();
1128 }
1129 return NULL;
1130}
1131
1132nub_size_t
1133DNBProcessGetArgumentCount (nub_process_t pid)
1134{
1135 MachProcessSP procSP;
1136 if (GetProcessSP (pid, procSP))
1137 {
1138 return procSP->ArgumentCount();
1139 }
1140 return 0;
1141}
1142
1143const char *
1144DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx)
1145{
1146 MachProcessSP procSP;
1147 if (GetProcessSP (pid, procSP))
1148 {
1149 return procSP->ArgumentAtIndex (idx);
1150 }
1151 return NULL;
1152}
1153
1154
1155//----------------------------------------------------------------------
1156// Execution control
1157//----------------------------------------------------------------------
1158nub_bool_t
1159DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions)
1160{
1161 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1162 MachProcessSP procSP;
1163 if (GetProcessSP (pid, procSP))
1164 {
1165 DNBThreadResumeActions thread_actions (actions, num_actions);
1166
1167 // Below we add a default thread plan just in case one wasn't
1168 // provided so all threads always know what they were supposed to do
1169 if (thread_actions.IsEmpty())
1170 {
1171 // No thread plans were given, so the default it to run all threads
1172 thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
1173 }
1174 else
1175 {
1176 // Some thread plans were given which means anything that wasn't
1177 // specified should remain stopped.
1178 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
1179 }
1180 return procSP->Resume (thread_actions);
1181 }
1182 return false;
1183}
1184
1185nub_bool_t
1186DNBProcessHalt (nub_process_t pid)
1187{
1188 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1189 MachProcessSP procSP;
1190 if (GetProcessSP (pid, procSP))
1191 return procSP->Signal (SIGSTOP);
1192 return false;
1193}
1194//
1195//nub_bool_t
1196//DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
1197//{
1198// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step);
1199// MachProcessSP procSP;
1200// if (GetProcessSP (pid, procSP))
1201// {
1202// return procSP->Resume(tid, step, 0);
1203// }
1204// return false;
1205//}
1206//
1207//nub_bool_t
1208//DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal)
1209//{
1210// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
1211// MachProcessSP procSP;
1212// if (GetProcessSP (pid, procSP))
1213// {
1214// return procSP->Resume(tid, step, signal);
1215// }
1216// return false;
1217//}
1218
1219nub_event_t
1220DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout)
1221{
1222 nub_event_t result = 0;
1223 MachProcessSP procSP;
1224 if (GetProcessSP (pid, procSP))
1225 {
1226 if (wait_for_set)
1227 result = procSP->Events().WaitForSetEvents(event_mask, timeout);
1228 else
1229 result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
1230 }
1231 return result;
1232}
1233
1234void
1235DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask)
1236{
1237 MachProcessSP procSP;
1238 if (GetProcessSP (pid, procSP))
1239 procSP->Events().ResetEvents(event_mask);
1240}
1241
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001242// Breakpoints
Greg Claytond8cf1a12013-06-12 00:46:38 +00001243nub_bool_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001244DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
1245{
1246 MachProcessSP procSP;
1247 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001248 return procSP->CreateBreakpoint(addr, size, hardware) != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001249 return false;
1250}
1251
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001252nub_bool_t
Greg Claytond8cf1a12013-06-12 00:46:38 +00001253DNBBreakpointClear (nub_process_t pid, nub_addr_t addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001254{
1255 MachProcessSP procSP;
1256 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001257 return procSP->DisableBreakpoint(addr, true);
1258 return false; // Failed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001259}
1260
Greg Claytond8cf1a12013-06-12 00:46:38 +00001261
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001262//----------------------------------------------------------------------
1263// Watchpoints
1264//----------------------------------------------------------------------
Greg Claytond8cf1a12013-06-12 00:46:38 +00001265nub_bool_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001266DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware)
1267{
1268 MachProcessSP procSP;
1269 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001270 return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001271 return false;
1272}
1273
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001274nub_bool_t
Greg Claytond8cf1a12013-06-12 00:46:38 +00001275DNBWatchpointClear (nub_process_t pid, nub_addr_t addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001276{
1277 MachProcessSP procSP;
1278 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001279 return procSP->DisableWatchpoint(addr, true);
1280 return false; // Failed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001281}
1282
1283//----------------------------------------------------------------------
Johnny Chen64637202012-05-23 21:09:52 +00001284// Return the number of supported hardware watchpoints.
1285//----------------------------------------------------------------------
1286uint32_t
1287DNBWatchpointGetNumSupportedHWP (nub_process_t pid)
1288{
1289 MachProcessSP procSP;
1290 if (GetProcessSP (pid, procSP))
1291 return procSP->GetNumSupportedHardwareWatchpoints();
1292 return 0;
1293}
1294
1295//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001296// Read memory in the address space of process PID. This call will take
1297// care of setting and restoring permissions and breaking up the memory
1298// read into multiple chunks as required.
1299//
1300// RETURNS: number of bytes actually read
1301//----------------------------------------------------------------------
1302nub_size_t
1303DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf)
1304{
1305 MachProcessSP procSP;
1306 if (GetProcessSP (pid, procSP))
1307 return procSP->ReadMemory(addr, size, buf);
1308 return 0;
1309}
1310
Greg Clayton0b90be12015-06-23 21:27:50 +00001311uint64_t
1312DNBProcessMemoryReadInteger (nub_process_t pid, nub_addr_t addr, nub_size_t integer_size, uint64_t fail_value)
1313{
1314 union Integers
1315 {
1316 uint8_t u8;
1317 uint16_t u16;
1318 uint32_t u32;
1319 uint64_t u64;
1320 };
1321
1322 if (integer_size <= sizeof(uint64_t))
1323 {
1324 Integers ints;
1325 if (DNBProcessMemoryRead(pid, addr, integer_size, &ints) == integer_size)
1326 {
1327 switch (integer_size)
1328 {
1329 case 1: return ints.u8;
1330 case 2: return ints.u16;
1331 case 3: return ints.u32 & 0xffffffu;
1332 case 4: return ints.u32;
1333 case 5: return ints.u32 & 0x000000ffffffffffull;
1334 case 6: return ints.u32 & 0x0000ffffffffffffull;
1335 case 7: return ints.u32 & 0x00ffffffffffffffull;
1336 case 8: return ints.u64;
1337 }
1338 }
1339 }
1340 return fail_value;
1341
1342}
1343
1344nub_addr_t
1345DNBProcessMemoryReadPointer (nub_process_t pid, nub_addr_t addr)
1346{
1347 cpu_type_t cputype = DNBProcessGetCPUType (pid);
1348 if (cputype)
1349 {
1350 const nub_size_t pointer_size = (cputype & CPU_ARCH_ABI64) ? 8 : 4;
1351 return DNBProcessMemoryReadInteger(pid, addr, pointer_size, 0);
1352 }
1353 return 0;
1354
1355}
1356
1357std::string
1358DNBProcessMemoryReadCString (nub_process_t pid, nub_addr_t addr)
1359{
1360 std::string cstr;
1361 char buffer[256];
1362 const nub_size_t max_buffer_cstr_length = sizeof(buffer)-1;
1363 buffer[max_buffer_cstr_length] = '\0';
1364 nub_size_t length = 0;
1365 nub_addr_t curr_addr = addr;
1366 do
1367 {
1368 nub_size_t bytes_read = DNBProcessMemoryRead(pid, curr_addr, max_buffer_cstr_length, buffer);
1369 if (bytes_read == 0)
1370 break;
1371 length = strlen(buffer);
1372 cstr.append(buffer, length);
1373 curr_addr += length;
1374 } while (length == max_buffer_cstr_length);
1375 return cstr;
1376}
1377
1378std::string
1379DNBProcessMemoryReadCStringFixed (nub_process_t pid, nub_addr_t addr, nub_size_t fixed_length)
1380{
1381 std::string cstr;
1382 char buffer[fixed_length+1];
1383 buffer[fixed_length] = '\0';
1384 nub_size_t bytes_read = DNBProcessMemoryRead(pid, addr, fixed_length, buffer);
1385 if (bytes_read > 0)
1386 cstr.assign(buffer);
1387 return cstr;
1388}
1389
1390
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001391//----------------------------------------------------------------------
1392// Write memory to the address space of process PID. This call will take
1393// care of setting and restoring permissions and breaking up the memory
1394// write into multiple chunks as required.
1395//
1396// RETURNS: number of bytes actually written
1397//----------------------------------------------------------------------
1398nub_size_t
1399DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf)
1400{
1401 MachProcessSP procSP;
1402 if (GetProcessSP (pid, procSP))
1403 return procSP->WriteMemory(addr, size, buf);
1404 return 0;
1405}
1406
1407nub_addr_t
1408DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions)
1409{
1410 MachProcessSP procSP;
1411 if (GetProcessSP (pid, procSP))
1412 return procSP->Task().AllocateMemory (size, permissions);
1413 return 0;
1414}
1415
1416nub_bool_t
1417DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr)
1418{
1419 MachProcessSP procSP;
1420 if (GetProcessSP (pid, procSP))
1421 return procSP->Task().DeallocateMemory (addr);
1422 return 0;
1423}
1424
Jason Molenda1f3966b2011-11-08 04:28:12 +00001425//----------------------------------------------------------------------
Jason Molenda3dc85832011-11-09 08:03:56 +00001426// Find attributes of the memory region that contains ADDR for process PID,
1427// if possible, and return a string describing those attributes.
Jason Molenda1f3966b2011-11-08 04:28:12 +00001428//
Jason Molenda3dc85832011-11-09 08:03:56 +00001429// Returns 1 if we could find attributes for this region and OUTBUF can
1430// be sent to the remote debugger.
Jason Molenda1f3966b2011-11-08 04:28:12 +00001431//
Jason Molenda3dc85832011-11-09 08:03:56 +00001432// Returns 0 if we couldn't find the attributes for a region of memory at
1433// that address and OUTBUF should not be sent.
1434//
1435// Returns -1 if this platform cannot look up information about memory regions
1436// or if we do not yet have a valid launched process.
1437//
Jason Molenda1f3966b2011-11-08 04:28:12 +00001438//----------------------------------------------------------------------
1439int
Greg Claytonfc5dd292011-12-12 18:51:14 +00001440DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info)
Jason Molenda1f3966b2011-11-08 04:28:12 +00001441{
1442 MachProcessSP procSP;
1443 if (GetProcessSP (pid, procSP))
Greg Clayton46fb5582011-11-18 07:03:08 +00001444 return procSP->Task().GetMemoryRegionInfo (addr, region_info);
1445
Jason Molenda1f3966b2011-11-08 04:28:12 +00001446 return -1;
1447}
1448
Han Ming Ong929a94f2012-11-29 22:14:45 +00001449std::string
Han Ming Ong8764fe72013-03-04 21:25:51 +00001450DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType)
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001451{
1452 MachProcessSP procSP;
1453 if (GetProcessSP (pid, procSP))
Han Ming Ong8764fe72013-03-04 21:25:51 +00001454 return procSP->Task().GetProfileData(scanType);
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001455
Han Ming Ong929a94f2012-11-29 22:14:45 +00001456 return std::string("");
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001457}
1458
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001459nub_bool_t
Han Ming Ong8764fe72013-03-04 21:25:51 +00001460DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001461{
1462 MachProcessSP procSP;
1463 if (GetProcessSP (pid, procSP))
1464 {
Han Ming Ong8764fe72013-03-04 21:25:51 +00001465 procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type);
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001466 return true;
1467 }
1468
1469 return false;
1470}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001471
1472//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001473// Get the number of threads for the specified process.
1474//----------------------------------------------------------------------
1475nub_size_t
1476DNBProcessGetNumThreads (nub_process_t pid)
1477{
1478 MachProcessSP procSP;
1479 if (GetProcessSP (pid, procSP))
1480 return procSP->GetNumThreads();
1481 return 0;
1482}
1483
1484//----------------------------------------------------------------------
1485// Get the thread ID of the current thread.
1486//----------------------------------------------------------------------
1487nub_thread_t
1488DNBProcessGetCurrentThread (nub_process_t pid)
1489{
1490 MachProcessSP procSP;
1491 if (GetProcessSP (pid, procSP))
1492 return procSP->GetCurrentThread();
1493 return 0;
1494}
1495
1496//----------------------------------------------------------------------
Jason Molendad5318c02013-04-03 04:18:47 +00001497// Get the mach port number of the current thread.
1498//----------------------------------------------------------------------
1499nub_thread_t
1500DNBProcessGetCurrentThreadMachPort (nub_process_t pid)
1501{
1502 MachProcessSP procSP;
1503 if (GetProcessSP (pid, procSP))
1504 return procSP->GetCurrentThreadMachPort();
1505 return 0;
1506}
1507
1508//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001509// Change the current thread.
1510//----------------------------------------------------------------------
1511nub_thread_t
1512DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid)
1513{
1514 MachProcessSP procSP;
1515 if (GetProcessSP (pid, procSP))
1516 return procSP->SetCurrentThread (tid);
1517 return INVALID_NUB_THREAD;
1518}
1519
1520
1521//----------------------------------------------------------------------
1522// Dump a string describing a thread's stop reason to the specified file
1523// handle
1524//----------------------------------------------------------------------
1525nub_bool_t
1526DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
1527{
1528 MachProcessSP procSP;
1529 if (GetProcessSP (pid, procSP))
1530 return procSP->GetThreadStoppedReason (tid, stop_info);
1531 return false;
1532}
1533
1534//----------------------------------------------------------------------
1535// Return string description for the specified thread.
1536//
1537// RETURNS: NULL if the thread isn't valid, else a NULL terminated C
1538// string from a static buffer that must be copied prior to subsequent
1539// calls.
1540//----------------------------------------------------------------------
1541const char *
1542DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid)
1543{
1544 MachProcessSP procSP;
1545 if (GetProcessSP (pid, procSP))
1546 return procSP->GetThreadInfo (tid);
1547 return NULL;
1548}
1549
1550//----------------------------------------------------------------------
1551// Get the thread ID given a thread index.
1552//----------------------------------------------------------------------
1553nub_thread_t
1554DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx)
1555{
1556 MachProcessSP procSP;
1557 if (GetProcessSP (pid, procSP))
1558 return procSP->GetThreadAtIndex (thread_idx);
1559 return INVALID_NUB_THREAD;
1560}
1561
Jim Ingham279ceec2012-07-25 21:12:43 +00001562//----------------------------------------------------------------------
1563// Do whatever is needed to sync the thread's register state with it's kernel values.
1564//----------------------------------------------------------------------
1565nub_bool_t
1566DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid)
1567{
1568 MachProcessSP procSP;
1569 if (GetProcessSP (pid, procSP))
1570 return procSP->SyncThreadState (tid);
1571 return false;
1572
1573}
1574
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001575nub_addr_t
1576DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid)
1577{
1578 MachProcessSP procSP;
1579 DNBError err;
1580 if (GetProcessSP (pid, procSP))
1581 return procSP->Task().GetDYLDAllImageInfosAddress (err);
1582 return INVALID_NUB_ADDRESS;
1583}
1584
1585
1586nub_bool_t
1587DNBProcessSharedLibrariesUpdated(nub_process_t pid)
1588{
1589 MachProcessSP procSP;
1590 if (GetProcessSP (pid, procSP))
1591 {
1592 procSP->SharedLibrariesUpdated ();
1593 return true;
1594 }
1595 return false;
1596}
1597
1598//----------------------------------------------------------------------
1599// Get the current shared library information for a process. Only return
1600// the shared libraries that have changed since the last shared library
1601// state changed event if only_changed is non-zero.
1602//----------------------------------------------------------------------
1603nub_size_t
1604DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos)
1605{
1606 MachProcessSP procSP;
1607 if (GetProcessSP (pid, procSP))
1608 return procSP->CopyImageInfos (image_infos, only_changed);
1609
1610 // If we have no process, then return NULL for the shared library info
1611 // and zero for shared library count
1612 *image_infos = NULL;
1613 return 0;
1614}
1615
Greg Claytond04f0ed2015-05-26 18:00:51 +00001616uint32_t
1617DNBGetRegisterCPUType()
1618{
1619 return DNBArchProtocol::GetRegisterCPUType ();
1620
1621}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001622//----------------------------------------------------------------------
1623// Get the register set information for a specific thread.
1624//----------------------------------------------------------------------
1625const DNBRegisterSetInfo *
1626DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
1627{
Greg Clayton3af9ea52010-11-18 05:57:03 +00001628 return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001629}
1630
1631
1632//----------------------------------------------------------------------
1633// Read a register value by register set and register index.
1634//----------------------------------------------------------------------
1635nub_bool_t
1636DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value)
1637{
1638 MachProcessSP procSP;
1639 ::bzero (value, sizeof(DNBRegisterValue));
1640 if (GetProcessSP (pid, procSP))
1641 {
1642 if (tid != INVALID_NUB_THREAD)
1643 return procSP->GetRegisterValue (tid, set, reg, value);
1644 }
1645 return false;
1646}
1647
1648nub_bool_t
1649DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value)
1650{
1651 if (tid != INVALID_NUB_THREAD)
1652 {
1653 MachProcessSP procSP;
1654 if (GetProcessSP (pid, procSP))
1655 return procSP->SetRegisterValue (tid, set, reg, value);
1656 }
1657 return false;
1658}
1659
1660nub_size_t
1661DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len)
1662{
1663 MachProcessSP procSP;
1664 if (GetProcessSP (pid, procSP))
1665 {
1666 if (tid != INVALID_NUB_THREAD)
1667 return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len);
1668 }
1669 ::bzero (buf, buf_len);
1670 return 0;
1671
1672}
1673
1674nub_size_t
1675DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len)
1676{
1677 MachProcessSP procSP;
1678 if (GetProcessSP (pid, procSP))
1679 {
1680 if (tid != INVALID_NUB_THREAD)
1681 return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len);
1682 }
1683 return 0;
1684}
1685
Greg Claytonf74cf862013-11-13 23:28:31 +00001686uint32_t
1687DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid)
1688{
1689 if (tid != INVALID_NUB_THREAD)
1690 {
1691 MachProcessSP procSP;
1692 if (GetProcessSP (pid, procSP))
1693 return procSP->GetThreadList().SaveRegisterState (tid);
1694 }
1695 return 0;
1696}
1697nub_bool_t
1698DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id)
1699{
1700 if (tid != INVALID_NUB_THREAD)
1701 {
1702 MachProcessSP procSP;
1703 if (GetProcessSP (pid, procSP))
1704 return procSP->GetThreadList().RestoreRegisterState (tid, save_id);
1705 }
1706 return false;
1707}
1708
1709
1710
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001711//----------------------------------------------------------------------
1712// Read a register value by name.
1713//----------------------------------------------------------------------
1714nub_bool_t
1715DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value)
1716{
1717 MachProcessSP procSP;
1718 ::bzero (value, sizeof(DNBRegisterValue));
1719 if (GetProcessSP (pid, procSP))
1720 {
1721 const struct DNBRegisterSetInfo *set_info;
1722 nub_size_t num_reg_sets = 0;
1723 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1724 if (set_info)
1725 {
1726 uint32_t set = reg_set;
1727 uint32_t reg;
1728 if (set == REGISTER_SET_ALL)
1729 {
1730 for (set = 1; set < num_reg_sets; ++set)
1731 {
1732 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1733 {
1734 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1735 return procSP->GetRegisterValue (tid, set, reg, value);
1736 }
1737 }
1738 }
1739 else
1740 {
1741 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1742 {
1743 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1744 return procSP->GetRegisterValue (tid, set, reg, value);
1745 }
1746 }
1747 }
1748 }
1749 return false;
1750}
1751
1752
1753//----------------------------------------------------------------------
1754// Read a register set and register number from the register name.
1755//----------------------------------------------------------------------
1756nub_bool_t
1757DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info)
1758{
1759 const struct DNBRegisterSetInfo *set_info;
1760 nub_size_t num_reg_sets = 0;
1761 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1762 if (set_info)
1763 {
1764 uint32_t set, reg;
1765 for (set = 1; set < num_reg_sets; ++set)
1766 {
1767 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1768 {
1769 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1770 {
1771 *info = set_info[set].registers[reg];
1772 return true;
1773 }
1774 }
1775 }
1776
1777 for (set = 1; set < num_reg_sets; ++set)
1778 {
1779 uint32_t reg;
1780 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1781 {
1782 if (set_info[set].registers[reg].alt == NULL)
1783 continue;
1784
1785 if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0)
1786 {
1787 *info = set_info[set].registers[reg];
1788 return true;
1789 }
1790 }
1791 }
1792 }
1793
1794 ::bzero (info, sizeof(DNBRegisterInfo));
1795 return false;
1796}
1797
1798
1799//----------------------------------------------------------------------
1800// Set the name to address callback function that this nub can use
1801// for any name to address lookups that are needed.
1802//----------------------------------------------------------------------
1803nub_bool_t
1804DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton)
1805{
1806 MachProcessSP procSP;
1807 if (GetProcessSP (pid, procSP))
1808 {
1809 procSP->SetNameToAddressCallback (callback, baton);
1810 return true;
1811 }
1812 return false;
1813}
1814
1815
1816//----------------------------------------------------------------------
1817// Set the name to address callback function that this nub can use
1818// for any name to address lookups that are needed.
1819//----------------------------------------------------------------------
1820nub_bool_t
1821DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton)
1822{
1823 MachProcessSP procSP;
1824 if (GetProcessSP (pid, procSP))
1825 {
1826 procSP->SetSharedLibraryInfoCallback (callback, baton);
1827 return true;
1828 }
1829 return false;
1830}
1831
1832nub_addr_t
1833DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib)
1834{
1835 MachProcessSP procSP;
1836 if (GetProcessSP (pid, procSP))
1837 {
1838 return procSP->LookupSymbol (name, shlib);
1839 }
1840 return INVALID_NUB_ADDRESS;
1841}
1842
1843
1844nub_size_t
1845DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size)
1846{
1847 MachProcessSP procSP;
1848 if (GetProcessSP (pid, procSP))
1849 return procSP->GetAvailableSTDOUT (buf, buf_size);
1850 return 0;
1851}
1852
1853nub_size_t
1854DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size)
1855{
1856 MachProcessSP procSP;
1857 if (GetProcessSP (pid, procSP))
1858 return procSP->GetAvailableSTDERR (buf, buf_size);
1859 return 0;
1860}
1861
1862nub_size_t
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001863DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size)
1864{
1865 MachProcessSP procSP;
1866 if (GetProcessSP (pid, procSP))
1867 return procSP->GetAsyncProfileData (buf, buf_size);
1868 return 0;
1869}
1870
1871nub_size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001872DNBProcessGetStopCount (nub_process_t pid)
1873{
1874 MachProcessSP procSP;
1875 if (GetProcessSP (pid, procSP))
1876 return procSP->StopCount();
1877 return 0;
1878}
1879
Greg Clayton71337622011-02-24 22:24:29 +00001880uint32_t
1881DNBProcessGetCPUType (nub_process_t pid)
1882{
1883 MachProcessSP procSP;
1884 if (GetProcessSP (pid, procSP))
1885 return procSP->GetCPUType ();
1886 return 0;
1887
1888}
1889
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001890nub_bool_t
1891DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
1892{
1893 if (path == NULL || path[0] == '\0')
1894 return false;
1895
1896 char max_path[PATH_MAX];
1897 std::string result;
1898 CFString::GlobPath(path, result);
1899
1900 if (result.empty())
1901 result = path;
Greg Clayton48baf7a2012-10-31 21:44:39 +00001902
1903 struct stat path_stat;
1904 if (::stat(path, &path_stat) == 0)
1905 {
1906 if ((path_stat.st_mode & S_IFMT) == S_IFDIR)
1907 {
1908 CFBundle bundle (path);
1909 CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
1910 if (url.get())
1911 {
1912 if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size))
1913 return true;
1914 }
1915 }
1916 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001917
1918 if (realpath(path, max_path))
1919 {
1920 // Found the path relatively...
1921 ::strncpy(resolved_path, max_path, resolved_path_size);
1922 return strlen(resolved_path) + 1 < resolved_path_size;
1923 }
1924 else
1925 {
1926 // Not a relative path, check the PATH environment variable if the
1927 const char *PATH = getenv("PATH");
1928 if (PATH)
1929 {
1930 const char *curr_path_start = PATH;
1931 const char *curr_path_end;
1932 while (curr_path_start && *curr_path_start)
1933 {
1934 curr_path_end = strchr(curr_path_start, ':');
1935 if (curr_path_end == NULL)
1936 {
1937 result.assign(curr_path_start);
1938 curr_path_start = NULL;
1939 }
1940 else if (curr_path_end > curr_path_start)
1941 {
1942 size_t len = curr_path_end - curr_path_start;
1943 result.assign(curr_path_start, len);
1944 curr_path_start += len + 1;
1945 }
1946 else
1947 break;
1948
1949 result += '/';
1950 result += path;
1951 struct stat s;
1952 if (stat(result.c_str(), &s) == 0)
1953 {
1954 ::strncpy(resolved_path, result.c_str(), resolved_path_size);
1955 return result.size() + 1 < resolved_path_size;
1956 }
1957 }
1958 }
1959 }
1960 return false;
1961}
1962
Jason Molenda6acc86c2015-08-12 03:27:33 +00001963bool
1964DNBGetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch)
1965{
1966 return MachProcess::GetOSVersionNumbers (major, minor, patch);
1967}
1968
Greg Clayton3af9ea52010-11-18 05:57:03 +00001969
1970void
1971DNBInitialize()
1972{
1973 DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
1974#if defined (__i386__) || defined (__x86_64__)
1975 DNBArchImplI386::Initialize();
1976 DNBArchImplX86_64::Initialize();
Todd Fiala013434e2014-07-09 01:29:05 +00001977#elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
Greg Clayton3af9ea52010-11-18 05:57:03 +00001978 DNBArchMachARM::Initialize();
Jason Molendaa3329782014-03-29 18:54:20 +00001979 DNBArchMachARM64::Initialize();
Greg Clayton3af9ea52010-11-18 05:57:03 +00001980#endif
1981}
1982
1983void
1984DNBTerminate()
1985{
1986}
Greg Clayton3c144382010-12-01 22:45:40 +00001987
1988nub_bool_t
1989DNBSetArchitecture (const char *arch)
1990{
1991 if (arch && arch[0])
1992 {
1993 if (strcasecmp (arch, "i386") == 0)
1994 return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386);
Greg Claytona86dc432014-01-22 23:42:03 +00001995 else if ((strcasecmp (arch, "x86_64") == 0) || (strcasecmp (arch, "x86_64h") == 0))
Greg Clayton3c144382010-12-01 22:45:40 +00001996 return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64);
Todd Fiala013434e2014-07-09 01:29:05 +00001997 else if (strstr (arch, "arm64") == arch || strstr (arch, "armv8") == arch || strstr (arch, "aarch64") == arch)
Jason Molendaa3329782014-03-29 18:54:20 +00001998 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM64);
Greg Clayton3c144382010-12-01 22:45:40 +00001999 else if (strstr (arch, "arm") == arch)
2000 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM);
2001 }
2002 return false;
2003}