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