blob: b5c2da96932bc75dd9002188df8351108e922a82 [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)
213 {
214 if (death_event.data & NOTE_VM_PRESSURE)
215 DNBProcessSetExitInfo (child_pid, "Terminated due to Memory Pressure");
216 else if (death_event.data & NOTE_VM_ERROR)
217 DNBProcessSetExitInfo (child_pid, "Terminated due to Memory Error");
218 else
219 DNBProcessSetExitInfo (child_pid, "Terminated due to unknown Memory condition");
220 }
221 else if (death_event.data & NOTE_EXIT_DECRYPTFAIL)
222 DNBProcessSetExitInfo (child_pid, "Terminated due to decrypt failure");
223 else if (death_event.data & NOTE_EXIT_CSERROR)
224 DNBProcessSetExitInfo (child_pid, "Terminated due to code signing error");
225
226 DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, exit_status);
227 DNBProcessSetExitStatus (child_pid, status);
228 return NULL;
229 }
Jason Molendaa3329782014-03-29 18:54:20 +0000230 }
231 }
232}
233
234static bool
235spawn_kqueue_thread (pid_t pid)
236{
237 pthread_t thread;
238 int kq_id;
239
240 kq_id = kqueue();
241 if (kq_id == -1)
242 {
243 DNBLogError ("Could not get kqueue for pid = %i.", pid);
244 return false;
245 }
246
247 struct kevent reg_event;
248
249 EV_SET(&reg_event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT|NOTE_EXIT_DETAIL, 0, NULL);
250 // Register the event:
251 int result = kevent (kq_id, &reg_event, 1, NULL, 0, NULL);
252 if (result != 0)
253 {
254 DNBLogError ("Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, result);
255 return false;
256 }
257
258 int ret = ::pthread_create (&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id);
259
260 // pthread_create returns 0 if successful
261 if (ret == 0)
262 {
263 ::pthread_detach (thread);
264 return true;
265 }
266 return false;
267}
268#endif // #if USE_KQUEUE
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000269
270static void *
271waitpid_thread (void *arg)
272{
273 const pid_t pid = (pid_t)(intptr_t)arg;
274 int status;
275 while (1)
276 {
277 pid_t child_pid = waitpid(pid, &status, 0);
Greg Clayton6467ff92013-06-27 00:23:57 +0000278 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 +0000279
280 if (child_pid < 0)
281 {
282 if (errno == EINTR)
283 continue;
284 break;
285 }
286 else
287 {
288 if (WIFSTOPPED(status))
289 {
290 continue;
291 }
292 else// if (WIFEXITED(status) || WIFSIGNALED(status))
293 {
Greg Clayton6467ff92013-06-27 00:23:57 +0000294 DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): setting exit status for pid = %i to %i", child_pid, status);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000295 DNBProcessSetExitStatus (child_pid, status);
296 return NULL;
297 }
298 }
299 }
300
301 // We should never exit as long as our child process is alive, so if we
302 // do something else went wrong and we should exit...
Greg Clayton6467ff92013-06-27 00:23:57 +0000303 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 +0000304 DNBProcessSetExitStatus (pid, -1);
305 return NULL;
306}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000307static bool
308spawn_waitpid_thread (pid_t pid)
309{
Jason Molendaa3329782014-03-29 18:54:20 +0000310#ifdef USE_KQUEUE
311 bool success = spawn_kqueue_thread (pid);
312 if (success)
313 return true;
314#endif
315
Jason Molenda27148b32013-10-05 02:52:22 +0000316 pthread_t thread;
317 int ret = ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid);
318 // pthread_create returns 0 if successful
319 if (ret == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000320 {
321 ::pthread_detach (thread);
322 return true;
323 }
324 return false;
325}
326
327nub_process_t
328DNBProcessLaunch (const char *path,
329 char const *argv[],
330 const char *envp[],
Greg Clayton6779606a2011-01-22 23:43:18 +0000331 const char *working_directory, // NULL => dont' change, non-NULL => set working directory for inferior to this
332 const char *stdin_path,
333 const char *stdout_path,
334 const char *stderr_path,
Caroline Ticef8da8632010-12-03 18:46:09 +0000335 bool no_stdio,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000336 nub_launch_flavor_t launch_flavor,
Greg Claytonf681b942010-08-31 18:35:14 +0000337 int disable_aslr,
Jason Molendaa3329782014-03-29 18:54:20 +0000338 const char *event_data,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000339 char *err_str,
340 size_t err_len)
341{
Greg Clayton43e0af02012-09-18 18:04:04 +0000342 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 +0000343 __FUNCTION__,
344 path,
345 argv,
346 envp,
347 working_directory,
348 stdin_path,
349 stdout_path,
350 stderr_path,
351 no_stdio,
352 launch_flavor,
353 disable_aslr,
354 err_str,
Greg Clayton43e0af02012-09-18 18:04:04 +0000355 (uint64_t)err_len);
Greg Claytonbd82a5d2011-01-23 05:56:20 +0000356
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000357 if (err_str && err_len > 0)
358 err_str[0] = '\0';
359 struct stat path_stat;
360 if (::stat(path, &path_stat) == -1)
361 {
362 char stat_error[256];
363 ::strerror_r (errno, stat_error, sizeof(stat_error));
364 snprintf(err_str, err_len, "%s (%s)", stat_error, path);
365 return INVALID_NUB_PROCESS;
366 }
367
368 MachProcessSP processSP (new MachProcess);
369 if (processSP.get())
370 {
371 DNBError launch_err;
Greg Clayton6779606a2011-01-22 23:43:18 +0000372 pid_t pid = processSP->LaunchForDebug (path,
373 argv,
374 envp,
375 working_directory,
376 stdin_path,
377 stdout_path,
378 stderr_path,
379 no_stdio,
380 launch_flavor,
Jason Molendaa3329782014-03-29 18:54:20 +0000381 disable_aslr,
382 event_data,
Greg Clayton6779606a2011-01-22 23:43:18 +0000383 launch_err);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000384 if (err_str)
385 {
386 *err_str = '\0';
387 if (launch_err.Fail())
388 {
389 const char *launch_err_str = launch_err.AsString();
390 if (launch_err_str)
391 {
392 strncpy(err_str, launch_err_str, err_len-1);
393 err_str[err_len-1] = '\0'; // Make sure the error string is terminated
394 }
395 }
396 }
397
398 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
399
400 if (pid != INVALID_NUB_PROCESS)
401 {
402 // Spawn a thread to reap our child inferior process...
403 spawn_waitpid_thread (pid);
404
405 if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL)
406 {
407 // We failed to get the task for our process ID which is bad.
Greg Claytonfb640c22012-02-02 19:23:22 +0000408 // Kill our process otherwise it will be stopped at the entry
409 // point and get reparented to someone else and never go away.
Jason Molenda153c8e02013-01-05 06:08:51 +0000410 DNBLog ("Could not get task port for process, sending SIGKILL and exiting.");
Greg Claytonfb640c22012-02-02 19:23:22 +0000411 kill (SIGKILL, pid);
412
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000413 if (err_str && err_len > 0)
414 {
415 if (launch_err.AsString())
416 {
417 ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString());
418 }
419 else
420 {
421 ::snprintf (err_str, err_len, "failed to get the task for process %i", pid);
422 }
423 }
424 }
425 else
426 {
Charles Davisb786e7d2012-02-21 00:53:12 +0000427 bool res = AddProcessToMap(pid, processSP);
428 assert(res && "Couldn't add process to map!");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000429 return pid;
430 }
431 }
432 }
433 return INVALID_NUB_PROCESS;
434}
435
436nub_process_t
437DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
438{
439 if (err_str && err_len > 0)
440 err_str[0] = '\0';
441 std::vector<struct kinfo_proc> matching_proc_infos;
442 size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
443 if (num_matching_proc_infos == 0)
444 {
445 DNBLogError ("error: no processes match '%s'\n", name);
446 return INVALID_NUB_PROCESS;
447 }
448 else if (num_matching_proc_infos > 1)
449 {
Greg Clayton43e0af02012-09-18 18:04:04 +0000450 DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000451 size_t i;
452 for (i=0; i<num_matching_proc_infos; ++i)
453 DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
454 return INVALID_NUB_PROCESS;
455 }
Greg Clayton3af9ea52010-11-18 05:57:03 +0000456
457 return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000458}
459
460nub_process_t
461DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len)
462{
463 if (err_str && err_len > 0)
464 err_str[0] = '\0';
465
Johnny Chen64503c82011-08-11 19:03:44 +0000466 pid_t pid = INVALID_NUB_PROCESS;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000467 MachProcessSP processSP(new MachProcess);
468 if (processSP.get())
469 {
470 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid);
471 pid = processSP->AttachForDebug (attach_pid, err_str, err_len);
472
473 if (pid != INVALID_NUB_PROCESS)
474 {
Charles Davisb786e7d2012-02-21 00:53:12 +0000475 bool res = AddProcessToMap(pid, processSP);
476 assert(res && "Couldn't add process to map!");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000477 spawn_waitpid_thread(pid);
478 }
479 }
480
481 while (pid != INVALID_NUB_PROCESS)
482 {
483 // Wait for process to start up and hit entry point
Greg Clayton3af9ea52010-11-18 05:57:03 +0000484 DNBLogThreadedIf (LOG_PROCESS,
485 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
486 __FUNCTION__,
487 pid);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000488 nub_event_t set_events = DNBProcessWaitForEvents (pid,
Greg Clayton3af9ea52010-11-18 05:57:03 +0000489 eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
490 true,
491 timeout);
492
493 DNBLogThreadedIf (LOG_PROCESS,
494 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
495 __FUNCTION__,
496 pid,
497 set_events);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000498
499 if (set_events == 0)
500 {
501 if (err_str && err_len > 0)
502 snprintf(err_str, err_len, "operation timed out");
503 pid = INVALID_NUB_PROCESS;
504 }
505 else
506 {
507 if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
508 {
509 nub_state_t pid_state = DNBProcessGetState (pid);
510 DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s",
511 __FUNCTION__, pid, DNBStateAsString(pid_state));
512
513 switch (pid_state)
514 {
Greg Clayton3af9ea52010-11-18 05:57:03 +0000515 default:
516 case eStateInvalid:
517 case eStateUnloaded:
518 case eStateAttaching:
519 case eStateLaunching:
520 case eStateSuspended:
521 break; // Ignore
522
523 case eStateRunning:
524 case eStateStepping:
525 // Still waiting to stop at entry point...
526 break;
527
528 case eStateStopped:
529 case eStateCrashed:
530 return pid;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000531
Greg Clayton3af9ea52010-11-18 05:57:03 +0000532 case eStateDetached:
533 case eStateExited:
534 if (err_str && err_len > 0)
535 snprintf(err_str, err_len, "process exited");
536 return INVALID_NUB_PROCESS;
537 }
538 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000539
540 DNBProcessResetEvents(pid, set_events);
541 }
542 }
543
544 return INVALID_NUB_PROCESS;
545}
546
Greg Clayton9eb4e032012-11-06 23:36:26 +0000547size_t
Greg Clayton3af9ea52010-11-18 05:57:03 +0000548GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000549{
Greg Clayton9eb4e032012-11-06 23:36:26 +0000550 size_t size = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000551 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
552 u_int namelen = sizeof(name)/sizeof(int);
553 int err;
554
555 // Try to find out how many processes are around so we can
556 // size the buffer appropriately. sysctl's man page specifically suggests
557 // this approach, and says it returns a bit larger size than needed to
558 // handle any new processes created between then and now.
559
560 err = ::sysctl (name, namelen, NULL, &size, NULL, 0);
561
562 if ((err < 0) && (err != ENOMEM))
563 {
564 proc_infos.clear();
565 perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
566 return 0;
567 }
568
569
570 // Increase the size of the buffer by a few processes in case more have
571 // been spawned
572 proc_infos.resize (size / sizeof(struct kinfo_proc));
573 size = proc_infos.size() * sizeof(struct kinfo_proc); // Make sure we don't exceed our resize...
574 err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0);
575 if (err < 0)
576 {
577 proc_infos.clear();
578 return 0;
579 }
580
581 // Trim down our array to fit what we actually got back
582 proc_infos.resize(size / sizeof(struct kinfo_proc));
583 return proc_infos.size();
584}
585
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000586static size_t
587GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos)
588{
589
590 matching_proc_infos.clear();
591 if (full_process_name && full_process_name[0])
592 {
593 // We only get the process name, not the full path, from the proc_info. So just take the
594 // base name of the process name...
595 const char *process_name;
596 process_name = strrchr (full_process_name, '/');
597 if (process_name == NULL)
Greg Clayton7dab2be2012-07-19 02:45:35 +0000598 process_name = full_process_name;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000599 else
Greg Clayton7dab2be2012-07-19 02:45:35 +0000600 process_name++;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000601
Greg Clayton7dab2be2012-07-19 02:45:35 +0000602 const int process_name_len = strlen(process_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000603 std::vector<struct kinfo_proc> proc_infos;
604 const size_t num_proc_infos = GetAllInfos(proc_infos);
605 if (num_proc_infos > 0)
606 {
607 uint32_t i;
608 for (i=0; i<num_proc_infos; i++)
609 {
610 // Skip zombie processes and processes with unset status
611 if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB)
612 continue;
613
614 // Check for process by name. We only check the first MAXCOMLEN
615 // chars as that is all that kp_proc.p_comm holds.
Jim Ingham490bccd2012-11-01 01:04:46 +0000616
Greg Clayton7dab2be2012-07-19 02:45:35 +0000617 if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000618 {
Greg Clayton7dab2be2012-07-19 02:45:35 +0000619 if (process_name_len > MAXCOMLEN)
620 {
621 // We found a matching process name whose first MAXCOMLEN
622 // characters match, but there is more to the name than
Jim Ingham490bccd2012-11-01 01:04:46 +0000623 // this. We need to get the full process name. Use proc_pidpath, which will get
624 // us the full path to the executed process.
Greg Clayton7dab2be2012-07-19 02:45:35 +0000625
Jim Ingham490bccd2012-11-01 01:04:46 +0000626 char proc_path_buf[PATH_MAX];
Greg Clayton7dab2be2012-07-19 02:45:35 +0000627
Jim Ingham490bccd2012-11-01 01:04:46 +0000628 int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX);
629 if (return_val > 0)
Greg Clayton7dab2be2012-07-19 02:45:35 +0000630 {
Jim Ingham490bccd2012-11-01 01:04:46 +0000631 // Okay, now search backwards from that to see if there is a
632 // slash in the name. Note, even though we got all the args we don't care
633 // because the list data is just a bunch of concatenated null terminated strings
634 // so strrchr will start from the end of argv0.
635
636 const char *argv_basename = strrchr(proc_path_buf, '/');
Greg Clayton7dab2be2012-07-19 02:45:35 +0000637 if (argv_basename)
638 {
639 // Skip the '/'
640 ++argv_basename;
641 }
642 else
643 {
644 // 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 +0000645 argv_basename = proc_path_buf;
Greg Clayton7dab2be2012-07-19 02:45:35 +0000646 }
647
648 if (argv_basename)
649 {
650 if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0)
651 {
652 matching_proc_infos.push_back(proc_infos[i]);
653 }
654 }
655 }
656 }
657 else
658 {
659 // We found a matching process, add it to our list
Greg Clayton7dab2be2012-07-19 02:45:35 +0000660 matching_proc_infos.push_back(proc_infos[i]);
661 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000662 }
663 }
664 }
665 }
666 // return the newly added matches.
667 return matching_proc_infos.size();
668}
669
670nub_process_t
Greg Clayton19388cf2010-10-18 01:45:30 +0000671DNBProcessAttachWait (const char *waitfor_process_name,
672 nub_launch_flavor_t launch_flavor,
Jim Inghamcd16df92012-07-20 21:37:13 +0000673 bool ignore_existing,
Greg Clayton19388cf2010-10-18 01:45:30 +0000674 struct timespec *timeout_abstime,
675 useconds_t waitfor_interval,
676 char *err_str,
677 size_t err_len,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000678 DNBShouldCancelCallback should_cancel_callback,
679 void *callback_data)
680{
681 DNBError prepare_error;
682 std::vector<struct kinfo_proc> exclude_proc_infos;
683 size_t num_exclude_proc_infos;
684
685 // If the PrepareForAttach returns a valid token, use MachProcess to check
686 // for the process, otherwise scan the process table.
687
688 const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error);
689
690 if (prepare_error.Fail())
691 {
692 DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString());
693 return INVALID_NUB_PROCESS;
694 }
695
696 if (attach_token == NULL)
Jim Inghamcd16df92012-07-20 21:37:13 +0000697 {
698 if (ignore_existing)
699 num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
700 else
701 num_exclude_proc_infos = 0;
702 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000703
704 DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
705
706 // Loop and try to find the process by name
707 nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
708
709 while (waitfor_pid == INVALID_NUB_PROCESS)
710 {
711 if (attach_token != NULL)
712 {
713 nub_process_t pid;
714 pid = MachProcess::CheckForProcess(attach_token);
715 if (pid != INVALID_NUB_PROCESS)
716 {
717 waitfor_pid = pid;
718 break;
719 }
720 }
721 else
722 {
723
724 // Get the current process list, and check for matches that
725 // aren't in our original list. If anyone wants to attach
726 // to an existing process by name, they should do it with
727 // --attach=PROCNAME. Else we will wait for the first matching
728 // process that wasn't in our exclusion list.
729 std::vector<struct kinfo_proc> proc_infos;
730 const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos);
731 for (size_t i=0; i<num_proc_infos; i++)
732 {
733 nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
734 for (size_t j=0; j<num_exclude_proc_infos; j++)
735 {
736 if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid)
737 {
738 // This process was in our exclusion list, don't use it.
739 curr_pid = INVALID_NUB_PROCESS;
740 break;
741 }
742 }
743
744 // If we didn't find CURR_PID in our exclusion list, then use it.
745 if (curr_pid != INVALID_NUB_PROCESS)
746 {
747 // We found our process!
748 waitfor_pid = curr_pid;
749 break;
750 }
751 }
752 }
753
754 // If we haven't found our process yet, check for a timeout
755 // and then sleep for a bit until we poll again.
756 if (waitfor_pid == INVALID_NUB_PROCESS)
757 {
758 if (timeout_abstime != NULL)
759 {
760 // Check to see if we have a waitfor-duration option that
761 // has timed out?
762 if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime))
763 {
764 if (err_str && err_len > 0)
765 snprintf(err_str, err_len, "operation timed out");
766 DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name);
767 return INVALID_NUB_PROCESS;
768 }
769 }
770
771 // Call the should cancel callback as well...
772
773 if (should_cancel_callback != NULL
774 && should_cancel_callback (callback_data))
775 {
776 DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback.");
777 waitfor_pid = INVALID_NUB_PROCESS;
778 break;
779 }
780
781 ::usleep (waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again
782 }
783 }
784
785 if (waitfor_pid != INVALID_NUB_PROCESS)
786 {
787 DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid);
788 waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len);
789 }
790
791 bool success = waitfor_pid != INVALID_NUB_PROCESS;
792 MachProcess::CleanupAfterAttach (attach_token, success, prepare_error);
793
794 return waitfor_pid;
795}
796
797nub_bool_t
798DNBProcessDetach (nub_process_t pid)
799{
800 MachProcessSP procSP;
801 if (GetProcessSP (pid, procSP))
802 {
Jim Ingham58813182014-02-25 04:53:13 +0000803 const bool remove = true;
804 DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid);
805 procSP->DisableAllBreakpoints(remove);
806 procSP->DisableAllWatchpoints (remove);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000807 return procSP->Detach();
808 }
809 return false;
810}
811
812nub_bool_t
813DNBProcessKill (nub_process_t pid)
814{
815 MachProcessSP procSP;
816 if (GetProcessSP (pid, procSP))
817 {
818 return procSP->Kill ();
819 }
820 return false;
821}
822
823nub_bool_t
824DNBProcessSignal (nub_process_t pid, int signal)
825{
826 MachProcessSP procSP;
827 if (GetProcessSP (pid, procSP))
828 {
829 return procSP->Signal (signal);
830 }
831 return false;
832}
833
Greg Clayton4296c222014-04-24 19:54:32 +0000834
835nub_bool_t
836DNBProcessInterrupt(nub_process_t pid)
837{
838 MachProcessSP procSP;
839 if (GetProcessSP (pid, procSP))
840 return procSP->Interrupt();
841 return false;
842}
843
Jason Molendaa3329782014-03-29 18:54:20 +0000844nub_bool_t
845DNBProcessSendEvent (nub_process_t pid, const char *event)
846{
847 MachProcessSP procSP;
848 if (GetProcessSP (pid, procSP))
849 {
850 // FIXME: Do something with the error...
851 DNBError send_error;
852 return procSP->SendEvent (event, send_error);
853 }
854 return false;
855}
856
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000857
858nub_bool_t
859DNBProcessIsAlive (nub_process_t pid)
860{
861 MachProcessSP procSP;
862 if (GetProcessSP (pid, procSP))
863 {
864 return MachTask::IsValid (procSP->Task().TaskPort());
865 }
866 return eStateInvalid;
867}
868
869//----------------------------------------------------------------------
870// Process and Thread state information
871//----------------------------------------------------------------------
872nub_state_t
873DNBProcessGetState (nub_process_t pid)
874{
875 MachProcessSP procSP;
876 if (GetProcessSP (pid, procSP))
877 {
878 return procSP->GetState();
879 }
880 return eStateInvalid;
881}
882
883//----------------------------------------------------------------------
884// Process and Thread state information
885//----------------------------------------------------------------------
886nub_bool_t
887DNBProcessGetExitStatus (nub_process_t pid, int* status)
888{
889 MachProcessSP procSP;
890 if (GetProcessSP (pid, procSP))
891 {
892 return procSP->GetExitStatus(status);
893 }
894 return false;
895}
896
897nub_bool_t
898DNBProcessSetExitStatus (nub_process_t pid, int status)
899{
900 MachProcessSP procSP;
901 if (GetProcessSP (pid, procSP))
902 {
903 procSP->SetExitStatus(status);
904 return true;
905 }
906 return false;
907}
908
Jason Molendaa3329782014-03-29 18:54:20 +0000909const char *
910DNBProcessGetExitInfo (nub_process_t pid)
911{
912 MachProcessSP procSP;
913 if (GetProcessSP (pid, procSP))
914 {
915 return procSP->GetExitInfo();
916 }
917 return NULL;
918}
919
920nub_bool_t
921DNBProcessSetExitInfo (nub_process_t pid, const char *info)
922{
923 MachProcessSP procSP;
924 if (GetProcessSP (pid, procSP))
925 {
926 procSP->SetExitInfo(info);
927 return true;
928 }
929 return false;
930}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000931
932const char *
933DNBThreadGetName (nub_process_t pid, nub_thread_t tid)
934{
935 MachProcessSP procSP;
936 if (GetProcessSP (pid, procSP))
937 return procSP->ThreadGetName(tid);
938 return NULL;
939}
940
941
942nub_bool_t
943DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info)
944{
945 MachProcessSP procSP;
946 if (GetProcessSP (pid, procSP))
947 return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
948 return false;
949}
950
951nub_state_t
952DNBThreadGetState (nub_process_t pid, nub_thread_t tid)
953{
954 MachProcessSP procSP;
955 if (GetProcessSP (pid, procSP))
956 {
957 return procSP->ThreadGetState(tid);
958 }
959 return eStateInvalid;
960}
961
962const char *
963DNBStateAsString(nub_state_t state)
964{
965 switch (state)
966 {
Greg Claytoneffe5c92011-05-03 22:09:39 +0000967 case eStateInvalid: return "Invalid";
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000968 case eStateUnloaded: return "Unloaded";
969 case eStateAttaching: return "Attaching";
970 case eStateLaunching: return "Launching";
971 case eStateStopped: return "Stopped";
972 case eStateRunning: return "Running";
973 case eStateStepping: return "Stepping";
974 case eStateCrashed: return "Crashed";
975 case eStateDetached: return "Detached";
976 case eStateExited: return "Exited";
977 case eStateSuspended: return "Suspended";
978 }
979 return "nub_state_t ???";
980}
981
Jason Molenda705b1802014-06-13 02:37:02 +0000982Genealogy::ThreadActivitySP
983DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out)
984{
985 Genealogy::ThreadActivitySP thread_activity_sp;
986 MachProcessSP procSP;
987 if (GetProcessSP (pid, procSP))
988 thread_activity_sp = procSP->GetGenealogyInfoForThread (tid, timed_out);
989 return thread_activity_sp;
990}
991
992Genealogy::ProcessExecutableInfoSP
993DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx)
994{
995 Genealogy::ProcessExecutableInfoSP image_info_sp;
996 MachProcessSP procSP;
997 if (GetProcessSP (pid, procSP))
998 {
999 image_info_sp = procSP->GetGenealogyImageInfo (idx);
1000 }
1001 return image_info_sp;
1002}
1003
1004ThreadInfo::QoS
1005DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index)
1006{
1007 MachProcessSP procSP;
1008 if (GetProcessSP (pid, procSP))
1009 {
1010 return procSP->GetRequestedQoS (tid, tsd, dti_qos_class_index);
1011 }
1012 return ThreadInfo::QoS();
1013}
1014
1015nub_addr_t
1016DNBGetPThreadT (nub_process_t pid, nub_thread_t tid)
1017{
1018 MachProcessSP procSP;
1019 if (GetProcessSP (pid, procSP))
1020 {
1021 return procSP->GetPThreadT (tid);
1022 }
1023 return INVALID_NUB_ADDRESS;
1024}
1025
1026nub_addr_t
1027DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid)
1028{
1029 MachProcessSP procSP;
1030 if (GetProcessSP (pid, procSP))
1031 {
1032 return procSP->GetDispatchQueueT (tid);
1033 }
1034 return INVALID_NUB_ADDRESS;
1035}
1036
1037nub_addr_t
1038DNBGetTSDAddressForThread (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)
1039{
1040 MachProcessSP procSP;
1041 if (GetProcessSP (pid, procSP))
1042 {
1043 return procSP->GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
1044 }
1045 return INVALID_NUB_ADDRESS;
1046}
1047
1048
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001049const char *
1050DNBProcessGetExecutablePath (nub_process_t pid)
1051{
1052 MachProcessSP procSP;
1053 if (GetProcessSP (pid, procSP))
1054 {
1055 return procSP->Path();
1056 }
1057 return NULL;
1058}
1059
1060nub_size_t
1061DNBProcessGetArgumentCount (nub_process_t pid)
1062{
1063 MachProcessSP procSP;
1064 if (GetProcessSP (pid, procSP))
1065 {
1066 return procSP->ArgumentCount();
1067 }
1068 return 0;
1069}
1070
1071const char *
1072DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx)
1073{
1074 MachProcessSP procSP;
1075 if (GetProcessSP (pid, procSP))
1076 {
1077 return procSP->ArgumentAtIndex (idx);
1078 }
1079 return NULL;
1080}
1081
1082
1083//----------------------------------------------------------------------
1084// Execution control
1085//----------------------------------------------------------------------
1086nub_bool_t
1087DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions)
1088{
1089 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1090 MachProcessSP procSP;
1091 if (GetProcessSP (pid, procSP))
1092 {
1093 DNBThreadResumeActions thread_actions (actions, num_actions);
1094
1095 // Below we add a default thread plan just in case one wasn't
1096 // provided so all threads always know what they were supposed to do
1097 if (thread_actions.IsEmpty())
1098 {
1099 // No thread plans were given, so the default it to run all threads
1100 thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
1101 }
1102 else
1103 {
1104 // Some thread plans were given which means anything that wasn't
1105 // specified should remain stopped.
1106 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
1107 }
1108 return procSP->Resume (thread_actions);
1109 }
1110 return false;
1111}
1112
1113nub_bool_t
1114DNBProcessHalt (nub_process_t pid)
1115{
1116 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1117 MachProcessSP procSP;
1118 if (GetProcessSP (pid, procSP))
1119 return procSP->Signal (SIGSTOP);
1120 return false;
1121}
1122//
1123//nub_bool_t
1124//DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
1125//{
1126// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step);
1127// MachProcessSP procSP;
1128// if (GetProcessSP (pid, procSP))
1129// {
1130// return procSP->Resume(tid, step, 0);
1131// }
1132// return false;
1133//}
1134//
1135//nub_bool_t
1136//DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal)
1137//{
1138// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
1139// MachProcessSP procSP;
1140// if (GetProcessSP (pid, procSP))
1141// {
1142// return procSP->Resume(tid, step, signal);
1143// }
1144// return false;
1145//}
1146
1147nub_event_t
1148DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout)
1149{
1150 nub_event_t result = 0;
1151 MachProcessSP procSP;
1152 if (GetProcessSP (pid, procSP))
1153 {
1154 if (wait_for_set)
1155 result = procSP->Events().WaitForSetEvents(event_mask, timeout);
1156 else
1157 result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
1158 }
1159 return result;
1160}
1161
1162void
1163DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask)
1164{
1165 MachProcessSP procSP;
1166 if (GetProcessSP (pid, procSP))
1167 procSP->Events().ResetEvents(event_mask);
1168}
1169
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001170// Breakpoints
Greg Claytond8cf1a12013-06-12 00:46:38 +00001171nub_bool_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001172DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
1173{
1174 MachProcessSP procSP;
1175 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001176 return procSP->CreateBreakpoint(addr, size, hardware) != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001177 return false;
1178}
1179
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001180nub_bool_t
Greg Claytond8cf1a12013-06-12 00:46:38 +00001181DNBBreakpointClear (nub_process_t pid, nub_addr_t addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001182{
1183 MachProcessSP procSP;
1184 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001185 return procSP->DisableBreakpoint(addr, true);
1186 return false; // Failed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001187}
1188
Greg Claytond8cf1a12013-06-12 00:46:38 +00001189
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001190//----------------------------------------------------------------------
1191// Watchpoints
1192//----------------------------------------------------------------------
Greg Claytond8cf1a12013-06-12 00:46:38 +00001193nub_bool_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001194DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware)
1195{
1196 MachProcessSP procSP;
1197 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001198 return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001199 return false;
1200}
1201
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001202nub_bool_t
Greg Claytond8cf1a12013-06-12 00:46:38 +00001203DNBWatchpointClear (nub_process_t pid, nub_addr_t addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001204{
1205 MachProcessSP procSP;
1206 if (GetProcessSP (pid, procSP))
Greg Claytond8cf1a12013-06-12 00:46:38 +00001207 return procSP->DisableWatchpoint(addr, true);
1208 return false; // Failed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001209}
1210
1211//----------------------------------------------------------------------
Johnny Chen64637202012-05-23 21:09:52 +00001212// Return the number of supported hardware watchpoints.
1213//----------------------------------------------------------------------
1214uint32_t
1215DNBWatchpointGetNumSupportedHWP (nub_process_t pid)
1216{
1217 MachProcessSP procSP;
1218 if (GetProcessSP (pid, procSP))
1219 return procSP->GetNumSupportedHardwareWatchpoints();
1220 return 0;
1221}
1222
1223//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001224// Read memory in the address space of process PID. This call will take
1225// care of setting and restoring permissions and breaking up the memory
1226// read into multiple chunks as required.
1227//
1228// RETURNS: number of bytes actually read
1229//----------------------------------------------------------------------
1230nub_size_t
1231DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf)
1232{
1233 MachProcessSP procSP;
1234 if (GetProcessSP (pid, procSP))
1235 return procSP->ReadMemory(addr, size, buf);
1236 return 0;
1237}
1238
1239//----------------------------------------------------------------------
1240// Write memory to the address space of process PID. This call will take
1241// care of setting and restoring permissions and breaking up the memory
1242// write into multiple chunks as required.
1243//
1244// RETURNS: number of bytes actually written
1245//----------------------------------------------------------------------
1246nub_size_t
1247DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf)
1248{
1249 MachProcessSP procSP;
1250 if (GetProcessSP (pid, procSP))
1251 return procSP->WriteMemory(addr, size, buf);
1252 return 0;
1253}
1254
1255nub_addr_t
1256DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions)
1257{
1258 MachProcessSP procSP;
1259 if (GetProcessSP (pid, procSP))
1260 return procSP->Task().AllocateMemory (size, permissions);
1261 return 0;
1262}
1263
1264nub_bool_t
1265DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr)
1266{
1267 MachProcessSP procSP;
1268 if (GetProcessSP (pid, procSP))
1269 return procSP->Task().DeallocateMemory (addr);
1270 return 0;
1271}
1272
Jason Molenda1f3966b2011-11-08 04:28:12 +00001273//----------------------------------------------------------------------
Jason Molenda3dc85832011-11-09 08:03:56 +00001274// Find attributes of the memory region that contains ADDR for process PID,
1275// if possible, and return a string describing those attributes.
Jason Molenda1f3966b2011-11-08 04:28:12 +00001276//
Jason Molenda3dc85832011-11-09 08:03:56 +00001277// Returns 1 if we could find attributes for this region and OUTBUF can
1278// be sent to the remote debugger.
Jason Molenda1f3966b2011-11-08 04:28:12 +00001279//
Jason Molenda3dc85832011-11-09 08:03:56 +00001280// Returns 0 if we couldn't find the attributes for a region of memory at
1281// that address and OUTBUF should not be sent.
1282//
1283// Returns -1 if this platform cannot look up information about memory regions
1284// or if we do not yet have a valid launched process.
1285//
Jason Molenda1f3966b2011-11-08 04:28:12 +00001286//----------------------------------------------------------------------
1287int
Greg Claytonfc5dd292011-12-12 18:51:14 +00001288DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info)
Jason Molenda1f3966b2011-11-08 04:28:12 +00001289{
1290 MachProcessSP procSP;
1291 if (GetProcessSP (pid, procSP))
Greg Clayton46fb5582011-11-18 07:03:08 +00001292 return procSP->Task().GetMemoryRegionInfo (addr, region_info);
1293
Jason Molenda1f3966b2011-11-08 04:28:12 +00001294 return -1;
1295}
1296
Han Ming Ong929a94f2012-11-29 22:14:45 +00001297std::string
Han Ming Ong8764fe72013-03-04 21:25:51 +00001298DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType)
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001299{
1300 MachProcessSP procSP;
1301 if (GetProcessSP (pid, procSP))
Han Ming Ong8764fe72013-03-04 21:25:51 +00001302 return procSP->Task().GetProfileData(scanType);
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001303
Han Ming Ong929a94f2012-11-29 22:14:45 +00001304 return std::string("");
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001305}
1306
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001307nub_bool_t
Han Ming Ong8764fe72013-03-04 21:25:51 +00001308DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001309{
1310 MachProcessSP procSP;
1311 if (GetProcessSP (pid, procSP))
1312 {
Han Ming Ong8764fe72013-03-04 21:25:51 +00001313 procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type);
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001314 return true;
1315 }
1316
1317 return false;
1318}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001319
1320//----------------------------------------------------------------------
1321// Formatted output that uses memory and registers from process and
1322// thread in place of arguments.
1323//----------------------------------------------------------------------
1324nub_size_t
1325DNBPrintf (nub_process_t pid, nub_thread_t tid, nub_addr_t base_addr, FILE *file, const char *format)
1326{
1327 if (file == NULL)
1328 return 0;
1329 enum printf_flags
1330 {
1331 alternate_form = (1 << 0),
1332 zero_padding = (1 << 1),
1333 negative_field_width = (1 << 2),
1334 blank_space = (1 << 3),
1335 show_sign = (1 << 4),
1336 show_thousands_separator= (1 << 5),
1337 };
1338
1339 enum printf_length_modifiers
1340 {
1341 length_mod_h = (1 << 0),
1342 length_mod_hh = (1 << 1),
1343 length_mod_l = (1 << 2),
1344 length_mod_ll = (1 << 3),
1345 length_mod_L = (1 << 4),
1346 length_mod_j = (1 << 5),
1347 length_mod_t = (1 << 6),
1348 length_mod_z = (1 << 7),
1349 length_mod_q = (1 << 8),
1350 };
1351
1352 nub_addr_t addr = base_addr;
1353 char *end_format = (char*)format + strlen(format);
1354 char *end = NULL; // For strtoXXXX calls;
1355 std::basic_string<uint8_t> buf;
1356 nub_size_t total_bytes_read = 0;
1357 DNBDataRef data;
1358 const char *f;
1359 for (f = format; *f != '\0' && f < end_format; f++)
1360 {
1361 char ch = *f;
1362 switch (ch)
1363 {
1364 case '%':
1365 {
1366 f++; // Skip the '%' character
Greg Clayton23f59502012-07-17 03:23:13 +00001367// int min_field_width = 0;
1368// int precision = 0;
1369 //uint32_t flags = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001370 uint32_t length_modifiers = 0;
1371 uint32_t byte_size = 0;
1372 uint32_t actual_byte_size = 0;
1373 bool is_string = false;
1374 bool is_register = false;
1375 DNBRegisterValue register_value;
1376 int64_t register_offset = 0;
1377 nub_addr_t register_addr = INVALID_NUB_ADDRESS;
1378
1379 // Create the format string to use for this conversion specification
1380 // so we can remove and mprintf specific flags and formatters.
1381 std::string fprintf_format("%");
1382
1383 // Decode any flags
1384 switch (*f)
1385 {
Greg Clayton23f59502012-07-17 03:23:13 +00001386 case '#': fprintf_format += *f++; break; //flags |= alternate_form; break;
1387 case '0': fprintf_format += *f++; break; //flags |= zero_padding; break;
1388 case '-': fprintf_format += *f++; break; //flags |= negative_field_width; break;
1389 case ' ': fprintf_format += *f++; break; //flags |= blank_space; break;
1390 case '+': fprintf_format += *f++; break; //flags |= show_sign; break;
1391 case ',': fprintf_format += *f++; break; //flags |= show_thousands_separator;break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001392 case '{':
1393 case '[':
1394 {
1395 // We have a register name specification that can take two forms:
1396 // ${regname} or ${regname+offset}
1397 // The action is to read the register value and add the signed offset
1398 // (if any) and use that as the value to format.
1399 // $[regname] or $[regname+offset]
1400 // The action is to read the register value and add the signed offset
1401 // (if any) and use the result as an address to dereference. The size
1402 // of what is dereferenced is specified by the actual byte size that
1403 // follows the minimum field width and precision (see comments below).
1404 switch (*f)
1405 {
1406 case '{':
1407 case '[':
1408 {
1409 char open_scope_ch = *f;
1410 f++;
1411 const char *reg_name = f;
1412 size_t reg_name_length = strcspn(f, "+-}]");
1413 if (reg_name_length > 0)
1414 {
1415 std::string register_name(reg_name, reg_name_length);
1416 f += reg_name_length;
1417 register_offset = strtoll(f, &end, 0);
1418 if (f < end)
1419 f = end;
1420 if ((open_scope_ch == '{' && *f != '}') || (open_scope_ch == '[' && *f != ']'))
1421 {
1422 fprintf(file, "error: Invalid register format string. Valid formats are %%{regname} or %%{regname+offset}, %%[regname] or %%[regname+offset]\n");
1423 return total_bytes_read;
1424 }
1425 else
1426 {
1427 f++;
1428 if (DNBThreadGetRegisterValueByName(pid, tid, REGISTER_SET_ALL, register_name.c_str(), &register_value))
1429 {
1430 // Set the address to dereference using the register value plus the offset
1431 switch (register_value.info.size)
1432 {
1433 default:
1434 case 0:
1435 fprintf (file, "error: unsupported register size of %u.\n", register_value.info.size);
1436 return total_bytes_read;
1437
1438 case 1: register_addr = register_value.value.uint8 + register_offset; break;
1439 case 2: register_addr = register_value.value.uint16 + register_offset; break;
1440 case 4: register_addr = register_value.value.uint32 + register_offset; break;
1441 case 8: register_addr = register_value.value.uint64 + register_offset; break;
1442 case 16:
1443 if (open_scope_ch == '[')
1444 {
1445 fprintf (file, "error: register size (%u) too large for address.\n", register_value.info.size);
1446 return total_bytes_read;
1447 }
1448 break;
1449 }
1450
1451 if (open_scope_ch == '{')
1452 {
1453 byte_size = register_value.info.size;
1454 is_register = true; // value is in a register
1455
1456 }
1457 else
1458 {
1459 addr = register_addr; // Use register value and offset as the address
1460 }
1461 }
1462 else
1463 {
Jason Molenda1c739112013-02-22 07:27:08 +00001464 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 +00001465 return total_bytes_read;
1466 }
1467 }
1468 }
1469 }
1470 break;
1471
1472 default:
1473 fprintf(file, "error: %%$ must be followed by (regname + n) or [regname + n]\n");
1474 return total_bytes_read;
1475 }
1476 }
1477 break;
1478 }
1479
1480 // Check for a minimum field width
1481 if (isdigit(*f))
1482 {
Greg Clayton23f59502012-07-17 03:23:13 +00001483 //min_field_width = strtoul(f, &end, 10);
1484 strtoul(f, &end, 10);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001485 if (end > f)
1486 {
1487 fprintf_format.append(f, end - f);
1488 f = end;
1489 }
1490 }
1491
1492
1493 // Check for a precision
1494 if (*f == '.')
1495 {
1496 f++;
1497 if (isdigit(*f))
1498 {
1499 fprintf_format += '.';
Greg Clayton23f59502012-07-17 03:23:13 +00001500 //precision = strtoul(f, &end, 10);
1501 strtoul(f, &end, 10);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001502 if (end > f)
1503 {
1504 fprintf_format.append(f, end - f);
1505 f = end;
1506 }
1507 }
1508 }
1509
1510
1511 // mprintf specific: read the optional actual byte size (abs)
1512 // after the standard minimum field width (mfw) and precision (prec).
1513 // Standard printf calls you can have "mfw.prec" or ".prec", but
1514 // mprintf can have "mfw.prec.abs", ".prec.abs" or "..abs". This is nice
1515 // for strings that may be in a fixed size buffer, but may not use all bytes
1516 // in that buffer for printable characters.
1517 if (*f == '.')
1518 {
1519 f++;
1520 actual_byte_size = strtoul(f, &end, 10);
1521 if (end > f)
1522 {
1523 byte_size = actual_byte_size;
1524 f = end;
1525 }
1526 }
1527
1528 // Decode the length modifiers
1529 switch (*f)
1530 {
1531 case 'h': // h and hh length modifiers
1532 fprintf_format += *f++;
1533 length_modifiers |= length_mod_h;
1534 if (*f == 'h')
1535 {
1536 fprintf_format += *f++;
1537 length_modifiers |= length_mod_hh;
1538 }
1539 break;
1540
1541 case 'l': // l and ll length modifiers
1542 fprintf_format += *f++;
1543 length_modifiers |= length_mod_l;
1544 if (*f == 'h')
1545 {
1546 fprintf_format += *f++;
1547 length_modifiers |= length_mod_ll;
1548 }
1549 break;
1550
1551 case 'L': fprintf_format += *f++; length_modifiers |= length_mod_L; break;
1552 case 'j': fprintf_format += *f++; length_modifiers |= length_mod_j; break;
1553 case 't': fprintf_format += *f++; length_modifiers |= length_mod_t; break;
1554 case 'z': fprintf_format += *f++; length_modifiers |= length_mod_z; break;
1555 case 'q': fprintf_format += *f++; length_modifiers |= length_mod_q; break;
1556 }
1557
1558 // Decode the conversion specifier
1559 switch (*f)
1560 {
1561 case '_':
1562 // mprintf specific format items
1563 {
1564 ++f; // Skip the '_' character
1565 switch (*f)
1566 {
1567 case 'a': // Print the current address
1568 ++f;
1569 fprintf_format += "ll";
1570 fprintf_format += *f; // actual format to show address with folows the 'a' ("%_ax")
1571 fprintf (file, fprintf_format.c_str(), addr);
1572 break;
1573 case 'o': // offset from base address
1574 ++f;
1575 fprintf_format += "ll";
1576 fprintf_format += *f; // actual format to show address with folows the 'a' ("%_ox")
1577 fprintf(file, fprintf_format.c_str(), addr - base_addr);
1578 break;
1579 default:
1580 fprintf (file, "error: unsupported mprintf specific format character '%c'.\n", *f);
1581 break;
1582 }
1583 continue;
1584 }
1585 break;
1586
1587 case 'D':
1588 case 'O':
1589 case 'U':
1590 fprintf_format += *f;
1591 if (byte_size == 0)
1592 byte_size = sizeof(long int);
1593 break;
1594
1595 case 'd':
1596 case 'i':
1597 case 'o':
1598 case 'u':
1599 case 'x':
1600 case 'X':
1601 fprintf_format += *f;
1602 if (byte_size == 0)
1603 {
1604 if (length_modifiers & length_mod_hh)
1605 byte_size = sizeof(char);
1606 else if (length_modifiers & length_mod_h)
1607 byte_size = sizeof(short);
Greg Clayton23f59502012-07-17 03:23:13 +00001608 else if (length_modifiers & length_mod_ll)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001609 byte_size = sizeof(long long);
1610 else if (length_modifiers & length_mod_l)
1611 byte_size = sizeof(long);
1612 else
1613 byte_size = sizeof(int);
1614 }
1615 break;
1616
1617 case 'a':
1618 case 'A':
1619 case 'f':
1620 case 'F':
1621 case 'e':
1622 case 'E':
1623 case 'g':
1624 case 'G':
1625 fprintf_format += *f;
1626 if (byte_size == 0)
1627 {
1628 if (length_modifiers & length_mod_L)
1629 byte_size = sizeof(long double);
1630 else
1631 byte_size = sizeof(double);
1632 }
1633 break;
1634
1635 case 'c':
1636 if ((length_modifiers & length_mod_l) == 0)
1637 {
1638 fprintf_format += *f;
1639 if (byte_size == 0)
1640 byte_size = sizeof(char);
1641 break;
1642 }
1643 // Fall through to 'C' modifier below...
1644
1645 case 'C':
1646 fprintf_format += *f;
1647 if (byte_size == 0)
1648 byte_size = sizeof(wchar_t);
1649 break;
1650
1651 case 's':
1652 fprintf_format += *f;
1653 if (is_register || byte_size == 0)
1654 is_string = 1;
1655 break;
1656
1657 case 'p':
1658 fprintf_format += *f;
1659 if (byte_size == 0)
1660 byte_size = sizeof(void*);
1661 break;
1662 }
1663
1664 if (is_string)
1665 {
1666 std::string mem_string;
1667 const size_t string_buf_len = 4;
1668 char string_buf[string_buf_len+1];
1669 char *string_buf_end = string_buf + string_buf_len;
1670 string_buf[string_buf_len] = '\0';
1671 nub_size_t bytes_read;
1672 nub_addr_t str_addr = is_register ? register_addr : addr;
1673 while ((bytes_read = DNBProcessMemoryRead(pid, str_addr, string_buf_len, &string_buf[0])) > 0)
1674 {
1675 // Did we get a NULL termination character yet?
1676 if (strchr(string_buf, '\0') == string_buf_end)
1677 {
1678 // no NULL terminator yet, append as a std::string
1679 mem_string.append(string_buf, string_buf_len);
1680 str_addr += string_buf_len;
1681 }
1682 else
1683 {
1684 // yep
1685 break;
1686 }
1687 }
1688 // Append as a C-string so we don't get the extra NULL
1689 // characters in the temp buffer (since it was resized)
1690 mem_string += string_buf;
1691 size_t mem_string_len = mem_string.size() + 1;
1692 fprintf(file, fprintf_format.c_str(), mem_string.c_str());
1693 if (mem_string_len > 0)
1694 {
1695 if (!is_register)
1696 {
1697 addr += mem_string_len;
1698 total_bytes_read += mem_string_len;
1699 }
1700 }
1701 else
1702 return total_bytes_read;
1703 }
1704 else
1705 if (byte_size > 0)
1706 {
1707 buf.resize(byte_size);
1708 nub_size_t bytes_read = 0;
1709 if (is_register)
1710 bytes_read = register_value.info.size;
1711 else
1712 bytes_read = DNBProcessMemoryRead(pid, addr, buf.size(), &buf[0]);
1713 if (bytes_read > 0)
1714 {
1715 if (!is_register)
1716 total_bytes_read += bytes_read;
1717
1718 if (bytes_read == byte_size)
1719 {
1720 switch (*f)
1721 {
1722 case 'd':
1723 case 'i':
1724 case 'o':
1725 case 'u':
1726 case 'X':
1727 case 'x':
1728 case 'a':
1729 case 'A':
1730 case 'f':
1731 case 'F':
1732 case 'e':
1733 case 'E':
1734 case 'g':
1735 case 'G':
1736 case 'p':
1737 case 'c':
1738 case 'C':
1739 {
1740 if (is_register)
1741 data.SetData(&register_value.value.v_uint8[0], register_value.info.size);
1742 else
1743 data.SetData(&buf[0], bytes_read);
1744 DNBDataRef::offset_t data_offset = 0;
1745 if (byte_size <= 4)
1746 {
1747 uint32_t u32 = data.GetMax32(&data_offset, byte_size);
1748 // Show the actual byte width when displaying hex
1749 fprintf(file, fprintf_format.c_str(), u32);
1750 }
1751 else if (byte_size <= 8)
1752 {
1753 uint64_t u64 = data.GetMax64(&data_offset, byte_size);
1754 // Show the actual byte width when displaying hex
1755 fprintf(file, fprintf_format.c_str(), u64);
1756 }
1757 else
1758 {
1759 fprintf(file, "error: integer size not supported, must be 8 bytes or less (%u bytes).\n", byte_size);
1760 }
1761 if (!is_register)
1762 addr += byte_size;
1763 }
1764 break;
1765
1766 case 's':
1767 fprintf(file, fprintf_format.c_str(), buf.c_str());
1768 addr += byte_size;
1769 break;
1770
1771 default:
1772 fprintf(file, "error: unsupported conversion specifier '%c'.\n", *f);
1773 break;
1774 }
1775 }
1776 }
1777 }
1778 else
1779 return total_bytes_read;
1780 }
1781 break;
1782
1783 case '\\':
1784 {
1785 f++;
1786 switch (*f)
1787 {
1788 case 'e': ch = '\e'; break;
1789 case 'a': ch = '\a'; break;
1790 case 'b': ch = '\b'; break;
1791 case 'f': ch = '\f'; break;
1792 case 'n': ch = '\n'; break;
1793 case 'r': ch = '\r'; break;
1794 case 't': ch = '\t'; break;
1795 case 'v': ch = '\v'; break;
1796 case '\'': ch = '\''; break;
1797 case '\\': ch = '\\'; break;
1798 case '0':
1799 case '1':
1800 case '2':
1801 case '3':
1802 case '4':
1803 case '5':
1804 case '6':
1805 case '7':
1806 ch = strtoul(f, &end, 8);
1807 f = end;
1808 break;
1809 default:
1810 ch = *f;
1811 break;
1812 }
1813 fputc(ch, file);
1814 }
1815 break;
1816
1817 default:
1818 fputc(ch, file);
1819 break;
1820 }
1821 }
1822 return total_bytes_read;
1823}
1824
1825
1826//----------------------------------------------------------------------
1827// Get the number of threads for the specified process.
1828//----------------------------------------------------------------------
1829nub_size_t
1830DNBProcessGetNumThreads (nub_process_t pid)
1831{
1832 MachProcessSP procSP;
1833 if (GetProcessSP (pid, procSP))
1834 return procSP->GetNumThreads();
1835 return 0;
1836}
1837
1838//----------------------------------------------------------------------
1839// Get the thread ID of the current thread.
1840//----------------------------------------------------------------------
1841nub_thread_t
1842DNBProcessGetCurrentThread (nub_process_t pid)
1843{
1844 MachProcessSP procSP;
1845 if (GetProcessSP (pid, procSP))
1846 return procSP->GetCurrentThread();
1847 return 0;
1848}
1849
1850//----------------------------------------------------------------------
Jason Molendad5318c02013-04-03 04:18:47 +00001851// Get the mach port number of the current thread.
1852//----------------------------------------------------------------------
1853nub_thread_t
1854DNBProcessGetCurrentThreadMachPort (nub_process_t pid)
1855{
1856 MachProcessSP procSP;
1857 if (GetProcessSP (pid, procSP))
1858 return procSP->GetCurrentThreadMachPort();
1859 return 0;
1860}
1861
1862//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001863// Change the current thread.
1864//----------------------------------------------------------------------
1865nub_thread_t
1866DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid)
1867{
1868 MachProcessSP procSP;
1869 if (GetProcessSP (pid, procSP))
1870 return procSP->SetCurrentThread (tid);
1871 return INVALID_NUB_THREAD;
1872}
1873
1874
1875//----------------------------------------------------------------------
1876// Dump a string describing a thread's stop reason to the specified file
1877// handle
1878//----------------------------------------------------------------------
1879nub_bool_t
1880DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
1881{
1882 MachProcessSP procSP;
1883 if (GetProcessSP (pid, procSP))
1884 return procSP->GetThreadStoppedReason (tid, stop_info);
1885 return false;
1886}
1887
1888//----------------------------------------------------------------------
1889// Return string description for the specified thread.
1890//
1891// RETURNS: NULL if the thread isn't valid, else a NULL terminated C
1892// string from a static buffer that must be copied prior to subsequent
1893// calls.
1894//----------------------------------------------------------------------
1895const char *
1896DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid)
1897{
1898 MachProcessSP procSP;
1899 if (GetProcessSP (pid, procSP))
1900 return procSP->GetThreadInfo (tid);
1901 return NULL;
1902}
1903
1904//----------------------------------------------------------------------
1905// Get the thread ID given a thread index.
1906//----------------------------------------------------------------------
1907nub_thread_t
1908DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx)
1909{
1910 MachProcessSP procSP;
1911 if (GetProcessSP (pid, procSP))
1912 return procSP->GetThreadAtIndex (thread_idx);
1913 return INVALID_NUB_THREAD;
1914}
1915
Jim Ingham279ceec2012-07-25 21:12:43 +00001916//----------------------------------------------------------------------
1917// Do whatever is needed to sync the thread's register state with it's kernel values.
1918//----------------------------------------------------------------------
1919nub_bool_t
1920DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid)
1921{
1922 MachProcessSP procSP;
1923 if (GetProcessSP (pid, procSP))
1924 return procSP->SyncThreadState (tid);
1925 return false;
1926
1927}
1928
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001929nub_addr_t
1930DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid)
1931{
1932 MachProcessSP procSP;
1933 DNBError err;
1934 if (GetProcessSP (pid, procSP))
1935 return procSP->Task().GetDYLDAllImageInfosAddress (err);
1936 return INVALID_NUB_ADDRESS;
1937}
1938
1939
1940nub_bool_t
1941DNBProcessSharedLibrariesUpdated(nub_process_t pid)
1942{
1943 MachProcessSP procSP;
1944 if (GetProcessSP (pid, procSP))
1945 {
1946 procSP->SharedLibrariesUpdated ();
1947 return true;
1948 }
1949 return false;
1950}
1951
1952//----------------------------------------------------------------------
1953// Get the current shared library information for a process. Only return
1954// the shared libraries that have changed since the last shared library
1955// state changed event if only_changed is non-zero.
1956//----------------------------------------------------------------------
1957nub_size_t
1958DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos)
1959{
1960 MachProcessSP procSP;
1961 if (GetProcessSP (pid, procSP))
1962 return procSP->CopyImageInfos (image_infos, only_changed);
1963
1964 // If we have no process, then return NULL for the shared library info
1965 // and zero for shared library count
1966 *image_infos = NULL;
1967 return 0;
1968}
1969
1970//----------------------------------------------------------------------
1971// Get the register set information for a specific thread.
1972//----------------------------------------------------------------------
1973const DNBRegisterSetInfo *
1974DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
1975{
Greg Clayton3af9ea52010-11-18 05:57:03 +00001976 return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001977}
1978
1979
1980//----------------------------------------------------------------------
1981// Read a register value by register set and register index.
1982//----------------------------------------------------------------------
1983nub_bool_t
1984DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value)
1985{
1986 MachProcessSP procSP;
1987 ::bzero (value, sizeof(DNBRegisterValue));
1988 if (GetProcessSP (pid, procSP))
1989 {
1990 if (tid != INVALID_NUB_THREAD)
1991 return procSP->GetRegisterValue (tid, set, reg, value);
1992 }
1993 return false;
1994}
1995
1996nub_bool_t
1997DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value)
1998{
1999 if (tid != INVALID_NUB_THREAD)
2000 {
2001 MachProcessSP procSP;
2002 if (GetProcessSP (pid, procSP))
2003 return procSP->SetRegisterValue (tid, set, reg, value);
2004 }
2005 return false;
2006}
2007
2008nub_size_t
2009DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len)
2010{
2011 MachProcessSP procSP;
2012 if (GetProcessSP (pid, procSP))
2013 {
2014 if (tid != INVALID_NUB_THREAD)
2015 return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len);
2016 }
2017 ::bzero (buf, buf_len);
2018 return 0;
2019
2020}
2021
2022nub_size_t
2023DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len)
2024{
2025 MachProcessSP procSP;
2026 if (GetProcessSP (pid, procSP))
2027 {
2028 if (tid != INVALID_NUB_THREAD)
2029 return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len);
2030 }
2031 return 0;
2032}
2033
Greg Claytonf74cf862013-11-13 23:28:31 +00002034uint32_t
2035DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid)
2036{
2037 if (tid != INVALID_NUB_THREAD)
2038 {
2039 MachProcessSP procSP;
2040 if (GetProcessSP (pid, procSP))
2041 return procSP->GetThreadList().SaveRegisterState (tid);
2042 }
2043 return 0;
2044}
2045nub_bool_t
2046DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id)
2047{
2048 if (tid != INVALID_NUB_THREAD)
2049 {
2050 MachProcessSP procSP;
2051 if (GetProcessSP (pid, procSP))
2052 return procSP->GetThreadList().RestoreRegisterState (tid, save_id);
2053 }
2054 return false;
2055}
2056
2057
2058
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002059//----------------------------------------------------------------------
2060// Read a register value by name.
2061//----------------------------------------------------------------------
2062nub_bool_t
2063DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value)
2064{
2065 MachProcessSP procSP;
2066 ::bzero (value, sizeof(DNBRegisterValue));
2067 if (GetProcessSP (pid, procSP))
2068 {
2069 const struct DNBRegisterSetInfo *set_info;
2070 nub_size_t num_reg_sets = 0;
2071 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
2072 if (set_info)
2073 {
2074 uint32_t set = reg_set;
2075 uint32_t reg;
2076 if (set == REGISTER_SET_ALL)
2077 {
2078 for (set = 1; set < num_reg_sets; ++set)
2079 {
2080 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2081 {
2082 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
2083 return procSP->GetRegisterValue (tid, set, reg, value);
2084 }
2085 }
2086 }
2087 else
2088 {
2089 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2090 {
2091 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
2092 return procSP->GetRegisterValue (tid, set, reg, value);
2093 }
2094 }
2095 }
2096 }
2097 return false;
2098}
2099
2100
2101//----------------------------------------------------------------------
2102// Read a register set and register number from the register name.
2103//----------------------------------------------------------------------
2104nub_bool_t
2105DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info)
2106{
2107 const struct DNBRegisterSetInfo *set_info;
2108 nub_size_t num_reg_sets = 0;
2109 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
2110 if (set_info)
2111 {
2112 uint32_t set, reg;
2113 for (set = 1; set < num_reg_sets; ++set)
2114 {
2115 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2116 {
2117 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
2118 {
2119 *info = set_info[set].registers[reg];
2120 return true;
2121 }
2122 }
2123 }
2124
2125 for (set = 1; set < num_reg_sets; ++set)
2126 {
2127 uint32_t reg;
2128 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2129 {
2130 if (set_info[set].registers[reg].alt == NULL)
2131 continue;
2132
2133 if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0)
2134 {
2135 *info = set_info[set].registers[reg];
2136 return true;
2137 }
2138 }
2139 }
2140 }
2141
2142 ::bzero (info, sizeof(DNBRegisterInfo));
2143 return false;
2144}
2145
2146
2147//----------------------------------------------------------------------
2148// Set the name to address callback function that this nub can use
2149// for any name to address lookups that are needed.
2150//----------------------------------------------------------------------
2151nub_bool_t
2152DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton)
2153{
2154 MachProcessSP procSP;
2155 if (GetProcessSP (pid, procSP))
2156 {
2157 procSP->SetNameToAddressCallback (callback, baton);
2158 return true;
2159 }
2160 return false;
2161}
2162
2163
2164//----------------------------------------------------------------------
2165// Set the name to address callback function that this nub can use
2166// for any name to address lookups that are needed.
2167//----------------------------------------------------------------------
2168nub_bool_t
2169DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton)
2170{
2171 MachProcessSP procSP;
2172 if (GetProcessSP (pid, procSP))
2173 {
2174 procSP->SetSharedLibraryInfoCallback (callback, baton);
2175 return true;
2176 }
2177 return false;
2178}
2179
2180nub_addr_t
2181DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib)
2182{
2183 MachProcessSP procSP;
2184 if (GetProcessSP (pid, procSP))
2185 {
2186 return procSP->LookupSymbol (name, shlib);
2187 }
2188 return INVALID_NUB_ADDRESS;
2189}
2190
2191
2192nub_size_t
2193DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size)
2194{
2195 MachProcessSP procSP;
2196 if (GetProcessSP (pid, procSP))
2197 return procSP->GetAvailableSTDOUT (buf, buf_size);
2198 return 0;
2199}
2200
2201nub_size_t
2202DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size)
2203{
2204 MachProcessSP procSP;
2205 if (GetProcessSP (pid, procSP))
2206 return procSP->GetAvailableSTDERR (buf, buf_size);
2207 return 0;
2208}
2209
2210nub_size_t
Han Ming Ongab3b8b22012-11-17 00:21:04 +00002211DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size)
2212{
2213 MachProcessSP procSP;
2214 if (GetProcessSP (pid, procSP))
2215 return procSP->GetAsyncProfileData (buf, buf_size);
2216 return 0;
2217}
2218
2219nub_size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002220DNBProcessGetStopCount (nub_process_t pid)
2221{
2222 MachProcessSP procSP;
2223 if (GetProcessSP (pid, procSP))
2224 return procSP->StopCount();
2225 return 0;
2226}
2227
Greg Clayton71337622011-02-24 22:24:29 +00002228uint32_t
2229DNBProcessGetCPUType (nub_process_t pid)
2230{
2231 MachProcessSP procSP;
2232 if (GetProcessSP (pid, procSP))
2233 return procSP->GetCPUType ();
2234 return 0;
2235
2236}
2237
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002238nub_bool_t
2239DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
2240{
2241 if (path == NULL || path[0] == '\0')
2242 return false;
2243
2244 char max_path[PATH_MAX];
2245 std::string result;
2246 CFString::GlobPath(path, result);
2247
2248 if (result.empty())
2249 result = path;
Greg Clayton48baf7a2012-10-31 21:44:39 +00002250
2251 struct stat path_stat;
2252 if (::stat(path, &path_stat) == 0)
2253 {
2254 if ((path_stat.st_mode & S_IFMT) == S_IFDIR)
2255 {
2256 CFBundle bundle (path);
2257 CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
2258 if (url.get())
2259 {
2260 if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size))
2261 return true;
2262 }
2263 }
2264 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002265
2266 if (realpath(path, max_path))
2267 {
2268 // Found the path relatively...
2269 ::strncpy(resolved_path, max_path, resolved_path_size);
2270 return strlen(resolved_path) + 1 < resolved_path_size;
2271 }
2272 else
2273 {
2274 // Not a relative path, check the PATH environment variable if the
2275 const char *PATH = getenv("PATH");
2276 if (PATH)
2277 {
2278 const char *curr_path_start = PATH;
2279 const char *curr_path_end;
2280 while (curr_path_start && *curr_path_start)
2281 {
2282 curr_path_end = strchr(curr_path_start, ':');
2283 if (curr_path_end == NULL)
2284 {
2285 result.assign(curr_path_start);
2286 curr_path_start = NULL;
2287 }
2288 else if (curr_path_end > curr_path_start)
2289 {
2290 size_t len = curr_path_end - curr_path_start;
2291 result.assign(curr_path_start, len);
2292 curr_path_start += len + 1;
2293 }
2294 else
2295 break;
2296
2297 result += '/';
2298 result += path;
2299 struct stat s;
2300 if (stat(result.c_str(), &s) == 0)
2301 {
2302 ::strncpy(resolved_path, result.c_str(), resolved_path_size);
2303 return result.size() + 1 < resolved_path_size;
2304 }
2305 }
2306 }
2307 }
2308 return false;
2309}
2310
Greg Clayton3af9ea52010-11-18 05:57:03 +00002311
2312void
2313DNBInitialize()
2314{
2315 DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
2316#if defined (__i386__) || defined (__x86_64__)
2317 DNBArchImplI386::Initialize();
2318 DNBArchImplX86_64::Initialize();
Jason Molendaa3329782014-03-29 18:54:20 +00002319#elif defined (__arm__) || defined (__arm64__)
Greg Clayton3af9ea52010-11-18 05:57:03 +00002320 DNBArchMachARM::Initialize();
Jason Molendaa3329782014-03-29 18:54:20 +00002321 DNBArchMachARM64::Initialize();
Greg Clayton3af9ea52010-11-18 05:57:03 +00002322#endif
2323}
2324
2325void
2326DNBTerminate()
2327{
2328}
Greg Clayton3c144382010-12-01 22:45:40 +00002329
2330nub_bool_t
2331DNBSetArchitecture (const char *arch)
2332{
2333 if (arch && arch[0])
2334 {
2335 if (strcasecmp (arch, "i386") == 0)
2336 return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386);
Greg Claytona86dc432014-01-22 23:42:03 +00002337 else if ((strcasecmp (arch, "x86_64") == 0) || (strcasecmp (arch, "x86_64h") == 0))
Greg Clayton3c144382010-12-01 22:45:40 +00002338 return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64);
Jason Molendaa3329782014-03-29 18:54:20 +00002339 else if (strstr (arch, "arm64") == arch || strstr (arch, "armv8") == arch)
2340 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM64);
Greg Clayton3c144382010-12-01 22:45:40 +00002341 else if (strstr (arch, "arm") == arch)
2342 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM);
2343 }
2344 return false;
2345}