blob: 3f7232d1791fc549830501df18327005f0f91ef5 [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"
15#include <signal.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <sys/resource.h>
19#include <sys/stat.h>
20#include <sys/types.h>
21#include <sys/wait.h>
22#include <unistd.h>
23#include <sys/sysctl.h>
24#include <map>
25#include <vector>
Jim Ingham490bccd2012-11-01 01:04:46 +000026#include <libproc.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027
28#include "MacOSX/MachProcess.h"
29#include "MacOSX/MachTask.h"
30#include "CFString.h"
31#include "DNBLog.h"
32#include "DNBDataRef.h"
33#include "DNBThreadResumeActions.h"
34#include "DNBTimer.h"
Greg Clayton48baf7a2012-10-31 21:44:39 +000035#include "CFBundle.h"
36
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037
Greg Claytond64afba2012-03-14 03:07:05 +000038typedef STD_SHARED_PTR(MachProcess) MachProcessSP;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000039typedef std::map<nub_process_t, MachProcessSP> ProcessMap;
40typedef ProcessMap::iterator ProcessMapIter;
41typedef ProcessMap::const_iterator ProcessMapConstIter;
42
Greg Clayton9eb4e032012-11-06 23:36:26 +000043size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos);
44static size_t GetAllInfosMatchingName (const char *process_name, std::vector<struct kinfo_proc>& matching_proc_infos);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000045
46//----------------------------------------------------------------------
47// A Thread safe singleton to get a process map pointer.
48//
49// Returns a pointer to the existing process map, or a pointer to a
50// newly created process map if CAN_CREATE is non-zero.
51//----------------------------------------------------------------------
52static ProcessMap*
53GetProcessMap(bool can_create)
54{
55 static ProcessMap* g_process_map_ptr = NULL;
56
57 if (can_create && g_process_map_ptr == NULL)
58 {
59 static pthread_mutex_t g_process_map_mutex = PTHREAD_MUTEX_INITIALIZER;
60 PTHREAD_MUTEX_LOCKER (locker, &g_process_map_mutex);
61 if (g_process_map_ptr == NULL)
62 g_process_map_ptr = new ProcessMap;
63 }
64 return g_process_map_ptr;
65}
66
67//----------------------------------------------------------------------
68// Add PID to the shared process pointer map.
69//
70// Return non-zero value if we succeed in adding the process to the map.
71// The only time this should fail is if we run out of memory and can't
72// allocate a ProcessMap.
73//----------------------------------------------------------------------
74static nub_bool_t
75AddProcessToMap (nub_process_t pid, MachProcessSP& procSP)
76{
77 ProcessMap* process_map = GetProcessMap(true);
78 if (process_map)
79 {
80 process_map->insert(std::make_pair(pid, procSP));
81 return true;
82 }
83 return false;
84}
85
86//----------------------------------------------------------------------
87// Remove the shared pointer for PID from the process map.
88//
89// Returns the number of items removed from the process map.
90//----------------------------------------------------------------------
91static size_t
92RemoveProcessFromMap (nub_process_t pid)
93{
94 ProcessMap* process_map = GetProcessMap(false);
95 if (process_map)
96 {
97 return process_map->erase(pid);
98 }
99 return 0;
100}
101
102//----------------------------------------------------------------------
103// Get the shared pointer for PID from the existing process map.
104//
105// Returns true if we successfully find a shared pointer to a
106// MachProcess object.
107//----------------------------------------------------------------------
108static nub_bool_t
109GetProcessSP (nub_process_t pid, MachProcessSP& procSP)
110{
111 ProcessMap* process_map = GetProcessMap(false);
112 if (process_map != NULL)
113 {
114 ProcessMapIter pos = process_map->find(pid);
115 if (pos != process_map->end())
116 {
117 procSP = pos->second;
118 return true;
119 }
120 }
121 procSP.reset();
122 return false;
123}
124
125
126static void *
127waitpid_thread (void *arg)
128{
129 const pid_t pid = (pid_t)(intptr_t)arg;
130 int status;
131 while (1)
132 {
133 pid_t child_pid = waitpid(pid, &status, 0);
134 DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): waitpid (pid = %i, &status, 0) => %i, status = %i, errno = %i", pid, child_pid, status, errno);
135
136 if (child_pid < 0)
137 {
138 if (errno == EINTR)
139 continue;
140 break;
141 }
142 else
143 {
144 if (WIFSTOPPED(status))
145 {
146 continue;
147 }
148 else// if (WIFEXITED(status) || WIFSIGNALED(status))
149 {
150 DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, status);
151 DNBProcessSetExitStatus (child_pid, status);
152 return NULL;
153 }
154 }
155 }
156
157 // We should never exit as long as our child process is alive, so if we
158 // do something else went wrong and we should exit...
159 DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): main loop exited, setting exit status to an invalid value (-1) for pid %i", pid);
160 DNBProcessSetExitStatus (pid, -1);
161 return NULL;
162}
163
164static bool
165spawn_waitpid_thread (pid_t pid)
166{
167 pthread_t thread = THREAD_NULL;
168 ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid);
169 if (thread != THREAD_NULL)
170 {
171 ::pthread_detach (thread);
172 return true;
173 }
174 return false;
175}
176
177nub_process_t
178DNBProcessLaunch (const char *path,
179 char const *argv[],
180 const char *envp[],
Greg Clayton6779606a2011-01-22 23:43:18 +0000181 const char *working_directory, // NULL => dont' change, non-NULL => set working directory for inferior to this
182 const char *stdin_path,
183 const char *stdout_path,
184 const char *stderr_path,
Caroline Ticef8da8632010-12-03 18:46:09 +0000185 bool no_stdio,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000186 nub_launch_flavor_t launch_flavor,
Greg Claytonf681b942010-08-31 18:35:14 +0000187 int disable_aslr,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188 char *err_str,
189 size_t err_len)
190{
Greg Clayton43e0af02012-09-18 18:04:04 +0000191 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 +0000192 __FUNCTION__,
193 path,
194 argv,
195 envp,
196 working_directory,
197 stdin_path,
198 stdout_path,
199 stderr_path,
200 no_stdio,
201 launch_flavor,
202 disable_aslr,
203 err_str,
Greg Clayton43e0af02012-09-18 18:04:04 +0000204 (uint64_t)err_len);
Greg Claytonbd82a5d2011-01-23 05:56:20 +0000205
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000206 if (err_str && err_len > 0)
207 err_str[0] = '\0';
208 struct stat path_stat;
209 if (::stat(path, &path_stat) == -1)
210 {
211 char stat_error[256];
212 ::strerror_r (errno, stat_error, sizeof(stat_error));
213 snprintf(err_str, err_len, "%s (%s)", stat_error, path);
214 return INVALID_NUB_PROCESS;
215 }
216
217 MachProcessSP processSP (new MachProcess);
218 if (processSP.get())
219 {
220 DNBError launch_err;
Greg Clayton6779606a2011-01-22 23:43:18 +0000221 pid_t pid = processSP->LaunchForDebug (path,
222 argv,
223 envp,
224 working_directory,
225 stdin_path,
226 stdout_path,
227 stderr_path,
228 no_stdio,
229 launch_flavor,
230 disable_aslr,
231 launch_err);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000232 if (err_str)
233 {
234 *err_str = '\0';
235 if (launch_err.Fail())
236 {
237 const char *launch_err_str = launch_err.AsString();
238 if (launch_err_str)
239 {
240 strncpy(err_str, launch_err_str, err_len-1);
241 err_str[err_len-1] = '\0'; // Make sure the error string is terminated
242 }
243 }
244 }
245
246 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
247
248 if (pid != INVALID_NUB_PROCESS)
249 {
250 // Spawn a thread to reap our child inferior process...
251 spawn_waitpid_thread (pid);
252
253 if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL)
254 {
255 // We failed to get the task for our process ID which is bad.
Greg Claytonfb640c22012-02-02 19:23:22 +0000256 // Kill our process otherwise it will be stopped at the entry
257 // point and get reparented to someone else and never go away.
Jason Molenda153c8e02013-01-05 06:08:51 +0000258 DNBLog ("Could not get task port for process, sending SIGKILL and exiting.");
Greg Claytonfb640c22012-02-02 19:23:22 +0000259 kill (SIGKILL, pid);
260
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000261 if (err_str && err_len > 0)
262 {
263 if (launch_err.AsString())
264 {
265 ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString());
266 }
267 else
268 {
269 ::snprintf (err_str, err_len, "failed to get the task for process %i", pid);
270 }
271 }
272 }
273 else
274 {
Charles Davisb786e7d2012-02-21 00:53:12 +0000275 bool res = AddProcessToMap(pid, processSP);
276 assert(res && "Couldn't add process to map!");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000277 return pid;
278 }
279 }
280 }
281 return INVALID_NUB_PROCESS;
282}
283
284nub_process_t
285DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
286{
287 if (err_str && err_len > 0)
288 err_str[0] = '\0';
289 std::vector<struct kinfo_proc> matching_proc_infos;
290 size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
291 if (num_matching_proc_infos == 0)
292 {
293 DNBLogError ("error: no processes match '%s'\n", name);
294 return INVALID_NUB_PROCESS;
295 }
296 else if (num_matching_proc_infos > 1)
297 {
Greg Clayton43e0af02012-09-18 18:04:04 +0000298 DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000299 size_t i;
300 for (i=0; i<num_matching_proc_infos; ++i)
301 DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
302 return INVALID_NUB_PROCESS;
303 }
Greg Clayton3af9ea52010-11-18 05:57:03 +0000304
305 return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000306}
307
308nub_process_t
309DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len)
310{
311 if (err_str && err_len > 0)
312 err_str[0] = '\0';
313
Johnny Chen64503c82011-08-11 19:03:44 +0000314 pid_t pid = INVALID_NUB_PROCESS;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000315 MachProcessSP processSP(new MachProcess);
316 if (processSP.get())
317 {
318 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid);
319 pid = processSP->AttachForDebug (attach_pid, err_str, err_len);
320
321 if (pid != INVALID_NUB_PROCESS)
322 {
Charles Davisb786e7d2012-02-21 00:53:12 +0000323 bool res = AddProcessToMap(pid, processSP);
324 assert(res && "Couldn't add process to map!");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000325 spawn_waitpid_thread(pid);
326 }
327 }
328
329 while (pid != INVALID_NUB_PROCESS)
330 {
331 // Wait for process to start up and hit entry point
Greg Clayton3af9ea52010-11-18 05:57:03 +0000332 DNBLogThreadedIf (LOG_PROCESS,
333 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
334 __FUNCTION__,
335 pid);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000336 nub_event_t set_events = DNBProcessWaitForEvents (pid,
Greg Clayton3af9ea52010-11-18 05:57:03 +0000337 eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
338 true,
339 timeout);
340
341 DNBLogThreadedIf (LOG_PROCESS,
342 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
343 __FUNCTION__,
344 pid,
345 set_events);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000346
347 if (set_events == 0)
348 {
349 if (err_str && err_len > 0)
350 snprintf(err_str, err_len, "operation timed out");
351 pid = INVALID_NUB_PROCESS;
352 }
353 else
354 {
355 if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
356 {
357 nub_state_t pid_state = DNBProcessGetState (pid);
358 DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s",
359 __FUNCTION__, pid, DNBStateAsString(pid_state));
360
361 switch (pid_state)
362 {
Greg Clayton3af9ea52010-11-18 05:57:03 +0000363 default:
364 case eStateInvalid:
365 case eStateUnloaded:
366 case eStateAttaching:
367 case eStateLaunching:
368 case eStateSuspended:
369 break; // Ignore
370
371 case eStateRunning:
372 case eStateStepping:
373 // Still waiting to stop at entry point...
374 break;
375
376 case eStateStopped:
377 case eStateCrashed:
378 return pid;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000379
Greg Clayton3af9ea52010-11-18 05:57:03 +0000380 case eStateDetached:
381 case eStateExited:
382 if (err_str && err_len > 0)
383 snprintf(err_str, err_len, "process exited");
384 return INVALID_NUB_PROCESS;
385 }
386 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387
388 DNBProcessResetEvents(pid, set_events);
389 }
390 }
391
392 return INVALID_NUB_PROCESS;
393}
394
Greg Clayton9eb4e032012-11-06 23:36:26 +0000395size_t
Greg Clayton3af9ea52010-11-18 05:57:03 +0000396GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397{
Greg Clayton9eb4e032012-11-06 23:36:26 +0000398 size_t size = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000399 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
400 u_int namelen = sizeof(name)/sizeof(int);
401 int err;
402
403 // Try to find out how many processes are around so we can
404 // size the buffer appropriately. sysctl's man page specifically suggests
405 // this approach, and says it returns a bit larger size than needed to
406 // handle any new processes created between then and now.
407
408 err = ::sysctl (name, namelen, NULL, &size, NULL, 0);
409
410 if ((err < 0) && (err != ENOMEM))
411 {
412 proc_infos.clear();
413 perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
414 return 0;
415 }
416
417
418 // Increase the size of the buffer by a few processes in case more have
419 // been spawned
420 proc_infos.resize (size / sizeof(struct kinfo_proc));
421 size = proc_infos.size() * sizeof(struct kinfo_proc); // Make sure we don't exceed our resize...
422 err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0);
423 if (err < 0)
424 {
425 proc_infos.clear();
426 return 0;
427 }
428
429 // Trim down our array to fit what we actually got back
430 proc_infos.resize(size / sizeof(struct kinfo_proc));
431 return proc_infos.size();
432}
433
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000434static size_t
435GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos)
436{
437
438 matching_proc_infos.clear();
439 if (full_process_name && full_process_name[0])
440 {
441 // We only get the process name, not the full path, from the proc_info. So just take the
442 // base name of the process name...
443 const char *process_name;
444 process_name = strrchr (full_process_name, '/');
445 if (process_name == NULL)
Greg Clayton7dab2be2012-07-19 02:45:35 +0000446 process_name = full_process_name;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000447 else
Greg Clayton7dab2be2012-07-19 02:45:35 +0000448 process_name++;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000449
Greg Clayton7dab2be2012-07-19 02:45:35 +0000450 const int process_name_len = strlen(process_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000451 std::vector<struct kinfo_proc> proc_infos;
452 const size_t num_proc_infos = GetAllInfos(proc_infos);
453 if (num_proc_infos > 0)
454 {
455 uint32_t i;
456 for (i=0; i<num_proc_infos; i++)
457 {
458 // Skip zombie processes and processes with unset status
459 if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB)
460 continue;
461
462 // Check for process by name. We only check the first MAXCOMLEN
463 // chars as that is all that kp_proc.p_comm holds.
Jim Ingham490bccd2012-11-01 01:04:46 +0000464
Greg Clayton7dab2be2012-07-19 02:45:35 +0000465 if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000466 {
Greg Clayton7dab2be2012-07-19 02:45:35 +0000467 if (process_name_len > MAXCOMLEN)
468 {
469 // We found a matching process name whose first MAXCOMLEN
470 // characters match, but there is more to the name than
Jim Ingham490bccd2012-11-01 01:04:46 +0000471 // this. We need to get the full process name. Use proc_pidpath, which will get
472 // us the full path to the executed process.
Greg Clayton7dab2be2012-07-19 02:45:35 +0000473
Jim Ingham490bccd2012-11-01 01:04:46 +0000474 char proc_path_buf[PATH_MAX];
Greg Clayton7dab2be2012-07-19 02:45:35 +0000475
Jim Ingham490bccd2012-11-01 01:04:46 +0000476 int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX);
477 if (return_val > 0)
Greg Clayton7dab2be2012-07-19 02:45:35 +0000478 {
Jim Ingham490bccd2012-11-01 01:04:46 +0000479 // Okay, now search backwards from that to see if there is a
480 // slash in the name. Note, even though we got all the args we don't care
481 // because the list data is just a bunch of concatenated null terminated strings
482 // so strrchr will start from the end of argv0.
483
484 const char *argv_basename = strrchr(proc_path_buf, '/');
Greg Clayton7dab2be2012-07-19 02:45:35 +0000485 if (argv_basename)
486 {
487 // Skip the '/'
488 ++argv_basename;
489 }
490 else
491 {
492 // 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 +0000493 argv_basename = proc_path_buf;
Greg Clayton7dab2be2012-07-19 02:45:35 +0000494 }
495
496 if (argv_basename)
497 {
498 if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0)
499 {
500 matching_proc_infos.push_back(proc_infos[i]);
501 }
502 }
503 }
504 }
505 else
506 {
507 // We found a matching process, add it to our list
Greg Clayton7dab2be2012-07-19 02:45:35 +0000508 matching_proc_infos.push_back(proc_infos[i]);
509 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000510 }
511 }
512 }
513 }
514 // return the newly added matches.
515 return matching_proc_infos.size();
516}
517
518nub_process_t
Greg Clayton19388cf2010-10-18 01:45:30 +0000519DNBProcessAttachWait (const char *waitfor_process_name,
520 nub_launch_flavor_t launch_flavor,
Jim Inghamcd16df92012-07-20 21:37:13 +0000521 bool ignore_existing,
Greg Clayton19388cf2010-10-18 01:45:30 +0000522 struct timespec *timeout_abstime,
523 useconds_t waitfor_interval,
524 char *err_str,
525 size_t err_len,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000526 DNBShouldCancelCallback should_cancel_callback,
527 void *callback_data)
528{
529 DNBError prepare_error;
530 std::vector<struct kinfo_proc> exclude_proc_infos;
531 size_t num_exclude_proc_infos;
532
533 // If the PrepareForAttach returns a valid token, use MachProcess to check
534 // for the process, otherwise scan the process table.
535
536 const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error);
537
538 if (prepare_error.Fail())
539 {
540 DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString());
541 return INVALID_NUB_PROCESS;
542 }
543
544 if (attach_token == NULL)
Jim Inghamcd16df92012-07-20 21:37:13 +0000545 {
546 if (ignore_existing)
547 num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
548 else
549 num_exclude_proc_infos = 0;
550 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000551
552 DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
553
554 // Loop and try to find the process by name
555 nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
556
557 while (waitfor_pid == INVALID_NUB_PROCESS)
558 {
559 if (attach_token != NULL)
560 {
561 nub_process_t pid;
562 pid = MachProcess::CheckForProcess(attach_token);
563 if (pid != INVALID_NUB_PROCESS)
564 {
565 waitfor_pid = pid;
566 break;
567 }
568 }
569 else
570 {
571
572 // Get the current process list, and check for matches that
573 // aren't in our original list. If anyone wants to attach
574 // to an existing process by name, they should do it with
575 // --attach=PROCNAME. Else we will wait for the first matching
576 // process that wasn't in our exclusion list.
577 std::vector<struct kinfo_proc> proc_infos;
578 const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos);
579 for (size_t i=0; i<num_proc_infos; i++)
580 {
581 nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
582 for (size_t j=0; j<num_exclude_proc_infos; j++)
583 {
584 if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid)
585 {
586 // This process was in our exclusion list, don't use it.
587 curr_pid = INVALID_NUB_PROCESS;
588 break;
589 }
590 }
591
592 // If we didn't find CURR_PID in our exclusion list, then use it.
593 if (curr_pid != INVALID_NUB_PROCESS)
594 {
595 // We found our process!
596 waitfor_pid = curr_pid;
597 break;
598 }
599 }
600 }
601
602 // If we haven't found our process yet, check for a timeout
603 // and then sleep for a bit until we poll again.
604 if (waitfor_pid == INVALID_NUB_PROCESS)
605 {
606 if (timeout_abstime != NULL)
607 {
608 // Check to see if we have a waitfor-duration option that
609 // has timed out?
610 if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime))
611 {
612 if (err_str && err_len > 0)
613 snprintf(err_str, err_len, "operation timed out");
614 DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name);
615 return INVALID_NUB_PROCESS;
616 }
617 }
618
619 // Call the should cancel callback as well...
620
621 if (should_cancel_callback != NULL
622 && should_cancel_callback (callback_data))
623 {
624 DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback.");
625 waitfor_pid = INVALID_NUB_PROCESS;
626 break;
627 }
628
629 ::usleep (waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again
630 }
631 }
632
633 if (waitfor_pid != INVALID_NUB_PROCESS)
634 {
635 DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid);
636 waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len);
637 }
638
639 bool success = waitfor_pid != INVALID_NUB_PROCESS;
640 MachProcess::CleanupAfterAttach (attach_token, success, prepare_error);
641
642 return waitfor_pid;
643}
644
645nub_bool_t
646DNBProcessDetach (nub_process_t pid)
647{
648 MachProcessSP procSP;
649 if (GetProcessSP (pid, procSP))
650 {
651 return procSP->Detach();
652 }
653 return false;
654}
655
656nub_bool_t
657DNBProcessKill (nub_process_t pid)
658{
659 MachProcessSP procSP;
660 if (GetProcessSP (pid, procSP))
661 {
662 return procSP->Kill ();
663 }
664 return false;
665}
666
667nub_bool_t
668DNBProcessSignal (nub_process_t pid, int signal)
669{
670 MachProcessSP procSP;
671 if (GetProcessSP (pid, procSP))
672 {
673 return procSP->Signal (signal);
674 }
675 return false;
676}
677
678
679nub_bool_t
680DNBProcessIsAlive (nub_process_t pid)
681{
682 MachProcessSP procSP;
683 if (GetProcessSP (pid, procSP))
684 {
685 return MachTask::IsValid (procSP->Task().TaskPort());
686 }
687 return eStateInvalid;
688}
689
690//----------------------------------------------------------------------
691// Process and Thread state information
692//----------------------------------------------------------------------
693nub_state_t
694DNBProcessGetState (nub_process_t pid)
695{
696 MachProcessSP procSP;
697 if (GetProcessSP (pid, procSP))
698 {
699 return procSP->GetState();
700 }
701 return eStateInvalid;
702}
703
704//----------------------------------------------------------------------
705// Process and Thread state information
706//----------------------------------------------------------------------
707nub_bool_t
708DNBProcessGetExitStatus (nub_process_t pid, int* status)
709{
710 MachProcessSP procSP;
711 if (GetProcessSP (pid, procSP))
712 {
713 return procSP->GetExitStatus(status);
714 }
715 return false;
716}
717
718nub_bool_t
719DNBProcessSetExitStatus (nub_process_t pid, int status)
720{
721 MachProcessSP procSP;
722 if (GetProcessSP (pid, procSP))
723 {
724 procSP->SetExitStatus(status);
725 return true;
726 }
727 return false;
728}
729
730
731const char *
732DNBThreadGetName (nub_process_t pid, nub_thread_t tid)
733{
734 MachProcessSP procSP;
735 if (GetProcessSP (pid, procSP))
736 return procSP->ThreadGetName(tid);
737 return NULL;
738}
739
740
741nub_bool_t
742DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info)
743{
744 MachProcessSP procSP;
745 if (GetProcessSP (pid, procSP))
746 return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
747 return false;
748}
749
750nub_state_t
751DNBThreadGetState (nub_process_t pid, nub_thread_t tid)
752{
753 MachProcessSP procSP;
754 if (GetProcessSP (pid, procSP))
755 {
756 return procSP->ThreadGetState(tid);
757 }
758 return eStateInvalid;
759}
760
761const char *
762DNBStateAsString(nub_state_t state)
763{
764 switch (state)
765 {
Greg Claytoneffe5c92011-05-03 22:09:39 +0000766 case eStateInvalid: return "Invalid";
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000767 case eStateUnloaded: return "Unloaded";
768 case eStateAttaching: return "Attaching";
769 case eStateLaunching: return "Launching";
770 case eStateStopped: return "Stopped";
771 case eStateRunning: return "Running";
772 case eStateStepping: return "Stepping";
773 case eStateCrashed: return "Crashed";
774 case eStateDetached: return "Detached";
775 case eStateExited: return "Exited";
776 case eStateSuspended: return "Suspended";
777 }
778 return "nub_state_t ???";
779}
780
781const char *
782DNBProcessGetExecutablePath (nub_process_t pid)
783{
784 MachProcessSP procSP;
785 if (GetProcessSP (pid, procSP))
786 {
787 return procSP->Path();
788 }
789 return NULL;
790}
791
792nub_size_t
793DNBProcessGetArgumentCount (nub_process_t pid)
794{
795 MachProcessSP procSP;
796 if (GetProcessSP (pid, procSP))
797 {
798 return procSP->ArgumentCount();
799 }
800 return 0;
801}
802
803const char *
804DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx)
805{
806 MachProcessSP procSP;
807 if (GetProcessSP (pid, procSP))
808 {
809 return procSP->ArgumentAtIndex (idx);
810 }
811 return NULL;
812}
813
814
815//----------------------------------------------------------------------
816// Execution control
817//----------------------------------------------------------------------
818nub_bool_t
819DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions)
820{
821 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
822 MachProcessSP procSP;
823 if (GetProcessSP (pid, procSP))
824 {
825 DNBThreadResumeActions thread_actions (actions, num_actions);
826
827 // Below we add a default thread plan just in case one wasn't
828 // provided so all threads always know what they were supposed to do
829 if (thread_actions.IsEmpty())
830 {
831 // No thread plans were given, so the default it to run all threads
832 thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
833 }
834 else
835 {
836 // Some thread plans were given which means anything that wasn't
837 // specified should remain stopped.
838 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
839 }
840 return procSP->Resume (thread_actions);
841 }
842 return false;
843}
844
845nub_bool_t
846DNBProcessHalt (nub_process_t pid)
847{
848 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
849 MachProcessSP procSP;
850 if (GetProcessSP (pid, procSP))
851 return procSP->Signal (SIGSTOP);
852 return false;
853}
854//
855//nub_bool_t
856//DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
857//{
858// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step);
859// MachProcessSP procSP;
860// if (GetProcessSP (pid, procSP))
861// {
862// return procSP->Resume(tid, step, 0);
863// }
864// return false;
865//}
866//
867//nub_bool_t
868//DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal)
869//{
870// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
871// MachProcessSP procSP;
872// if (GetProcessSP (pid, procSP))
873// {
874// return procSP->Resume(tid, step, signal);
875// }
876// return false;
877//}
878
879nub_event_t
880DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout)
881{
882 nub_event_t result = 0;
883 MachProcessSP procSP;
884 if (GetProcessSP (pid, procSP))
885 {
886 if (wait_for_set)
887 result = procSP->Events().WaitForSetEvents(event_mask, timeout);
888 else
889 result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
890 }
891 return result;
892}
893
894void
895DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask)
896{
897 MachProcessSP procSP;
898 if (GetProcessSP (pid, procSP))
899 procSP->Events().ResetEvents(event_mask);
900}
901
902void
903DNBProcessInterruptEvents (nub_process_t pid)
904{
905 MachProcessSP procSP;
906 if (GetProcessSP (pid, procSP))
907 procSP->Events().SetEvents(eEventProcessAsyncInterrupt);
908}
909
910
911// Breakpoints
912nub_break_t
913DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
914{
915 MachProcessSP procSP;
916 if (GetProcessSP (pid, procSP))
917 {
918 return procSP->CreateBreakpoint(addr, size, hardware, THREAD_NULL);
919 }
920 return INVALID_NUB_BREAK_ID;
921}
922
923nub_bool_t
924DNBBreakpointClear (nub_process_t pid, nub_break_t breakID)
925{
926 if (NUB_BREAK_ID_IS_VALID(breakID))
927 {
928 MachProcessSP procSP;
929 if (GetProcessSP (pid, procSP))
930 {
931 return procSP->DisableBreakpoint(breakID, true);
932 }
933 }
934 return false; // Failed
935}
936
937nub_ssize_t
938DNBBreakpointGetHitCount (nub_process_t pid, nub_break_t breakID)
939{
940 if (NUB_BREAK_ID_IS_VALID(breakID))
941 {
942 MachProcessSP procSP;
943 if (GetProcessSP (pid, procSP))
944 {
945 DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID);
946 if (bp)
947 return bp->GetHitCount();
948 }
949 }
950 return 0;
951}
952
953nub_ssize_t
954DNBBreakpointGetIgnoreCount (nub_process_t pid, nub_break_t breakID)
955{
956 if (NUB_BREAK_ID_IS_VALID(breakID))
957 {
958 MachProcessSP procSP;
959 if (GetProcessSP (pid, procSP))
960 {
961 DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID);
962 if (bp)
963 return bp->GetIgnoreCount();
964 }
965 }
966 return 0;
967}
968
969nub_bool_t
970DNBBreakpointSetIgnoreCount (nub_process_t pid, nub_break_t breakID, nub_size_t ignore_count)
971{
972 if (NUB_BREAK_ID_IS_VALID(breakID))
973 {
974 MachProcessSP procSP;
975 if (GetProcessSP (pid, procSP))
976 {
977 DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID);
978 if (bp)
979 {
980 bp->SetIgnoreCount(ignore_count);
981 return true;
982 }
983 }
984 }
985 return false;
986}
987
988// Set the callback function for a given breakpoint. The callback function will
989// get called as soon as the breakpoint is hit. The function will be called
990// with the process ID, thread ID, breakpoint ID and the baton, and can return
991//
992nub_bool_t
993DNBBreakpointSetCallback (nub_process_t pid, nub_break_t breakID, DNBCallbackBreakpointHit callback, void *baton)
994{
995 if (NUB_BREAK_ID_IS_VALID(breakID))
996 {
997 MachProcessSP procSP;
998 if (GetProcessSP (pid, procSP))
999 {
1000 DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID);
1001 if (bp)
1002 {
1003 bp->SetCallback(callback, baton);
1004 return true;
1005 }
1006 }
1007 }
1008 return false;
1009}
1010
1011//----------------------------------------------------------------------
1012// Dump the breakpoints stats for process PID for a breakpoint by ID.
1013//----------------------------------------------------------------------
1014void
1015DNBBreakpointPrint (nub_process_t pid, nub_break_t breakID)
1016{
1017 MachProcessSP procSP;
1018 if (GetProcessSP (pid, procSP))
1019 procSP->DumpBreakpoint(breakID);
1020}
1021
1022//----------------------------------------------------------------------
1023// Watchpoints
1024//----------------------------------------------------------------------
1025nub_watch_t
1026DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware)
1027{
1028 MachProcessSP procSP;
1029 if (GetProcessSP (pid, procSP))
1030 {
1031 return procSP->CreateWatchpoint(addr, size, watch_flags, hardware, THREAD_NULL);
1032 }
Johnny Chen86f97a42011-09-06 19:52:49 +00001033 return INVALID_NUB_WATCH_ID;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001034}
1035
1036nub_bool_t
1037DNBWatchpointClear (nub_process_t pid, nub_watch_t watchID)
1038{
Johnny Chen86f97a42011-09-06 19:52:49 +00001039 if (NUB_WATCH_ID_IS_VALID(watchID))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001040 {
1041 MachProcessSP procSP;
1042 if (GetProcessSP (pid, procSP))
1043 {
1044 return procSP->DisableWatchpoint(watchID, true);
1045 }
1046 }
1047 return false; // Failed
1048}
1049
1050nub_ssize_t
1051DNBWatchpointGetHitCount (nub_process_t pid, nub_watch_t watchID)
1052{
Johnny Chen86f97a42011-09-06 19:52:49 +00001053 if (NUB_WATCH_ID_IS_VALID(watchID))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001054 {
1055 MachProcessSP procSP;
1056 if (GetProcessSP (pid, procSP))
1057 {
1058 DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID);
1059 if (bp)
1060 return bp->GetHitCount();
1061 }
1062 }
1063 return 0;
1064}
1065
1066nub_ssize_t
1067DNBWatchpointGetIgnoreCount (nub_process_t pid, nub_watch_t watchID)
1068{
Johnny Chen86f97a42011-09-06 19:52:49 +00001069 if (NUB_WATCH_ID_IS_VALID(watchID))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001070 {
1071 MachProcessSP procSP;
1072 if (GetProcessSP (pid, procSP))
1073 {
1074 DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID);
1075 if (bp)
1076 return bp->GetIgnoreCount();
1077 }
1078 }
1079 return 0;
1080}
1081
1082nub_bool_t
1083DNBWatchpointSetIgnoreCount (nub_process_t pid, nub_watch_t watchID, nub_size_t ignore_count)
1084{
Johnny Chen86f97a42011-09-06 19:52:49 +00001085 if (NUB_WATCH_ID_IS_VALID(watchID))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001086 {
1087 MachProcessSP procSP;
1088 if (GetProcessSP (pid, procSP))
1089 {
1090 DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID);
1091 if (bp)
1092 {
1093 bp->SetIgnoreCount(ignore_count);
1094 return true;
1095 }
1096 }
1097 }
1098 return false;
1099}
1100
1101// Set the callback function for a given watchpoint. The callback function will
1102// get called as soon as the watchpoint is hit. The function will be called
1103// with the process ID, thread ID, watchpoint ID and the baton, and can return
1104//
1105nub_bool_t
1106DNBWatchpointSetCallback (nub_process_t pid, nub_watch_t watchID, DNBCallbackBreakpointHit callback, void *baton)
1107{
Johnny Chen86f97a42011-09-06 19:52:49 +00001108 if (NUB_WATCH_ID_IS_VALID(watchID))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001109 {
1110 MachProcessSP procSP;
1111 if (GetProcessSP (pid, procSP))
1112 {
1113 DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID);
1114 if (bp)
1115 {
1116 bp->SetCallback(callback, baton);
1117 return true;
1118 }
1119 }
1120 }
1121 return false;
1122}
1123
1124//----------------------------------------------------------------------
1125// Dump the watchpoints stats for process PID for a watchpoint by ID.
1126//----------------------------------------------------------------------
1127void
1128DNBWatchpointPrint (nub_process_t pid, nub_watch_t watchID)
1129{
1130 MachProcessSP procSP;
1131 if (GetProcessSP (pid, procSP))
1132 procSP->DumpWatchpoint(watchID);
1133}
1134
1135//----------------------------------------------------------------------
Johnny Chen64637202012-05-23 21:09:52 +00001136// Return the number of supported hardware watchpoints.
1137//----------------------------------------------------------------------
1138uint32_t
1139DNBWatchpointGetNumSupportedHWP (nub_process_t pid)
1140{
1141 MachProcessSP procSP;
1142 if (GetProcessSP (pid, procSP))
1143 return procSP->GetNumSupportedHardwareWatchpoints();
1144 return 0;
1145}
1146
1147//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001148// Read memory in the address space of process PID. This call will take
1149// care of setting and restoring permissions and breaking up the memory
1150// read into multiple chunks as required.
1151//
1152// RETURNS: number of bytes actually read
1153//----------------------------------------------------------------------
1154nub_size_t
1155DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf)
1156{
1157 MachProcessSP procSP;
1158 if (GetProcessSP (pid, procSP))
1159 return procSP->ReadMemory(addr, size, buf);
1160 return 0;
1161}
1162
1163//----------------------------------------------------------------------
1164// Write memory to the address space of process PID. This call will take
1165// care of setting and restoring permissions and breaking up the memory
1166// write into multiple chunks as required.
1167//
1168// RETURNS: number of bytes actually written
1169//----------------------------------------------------------------------
1170nub_size_t
1171DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf)
1172{
1173 MachProcessSP procSP;
1174 if (GetProcessSP (pid, procSP))
1175 return procSP->WriteMemory(addr, size, buf);
1176 return 0;
1177}
1178
1179nub_addr_t
1180DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions)
1181{
1182 MachProcessSP procSP;
1183 if (GetProcessSP (pid, procSP))
1184 return procSP->Task().AllocateMemory (size, permissions);
1185 return 0;
1186}
1187
1188nub_bool_t
1189DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr)
1190{
1191 MachProcessSP procSP;
1192 if (GetProcessSP (pid, procSP))
1193 return procSP->Task().DeallocateMemory (addr);
1194 return 0;
1195}
1196
Jason Molenda1f3966b2011-11-08 04:28:12 +00001197//----------------------------------------------------------------------
Jason Molenda3dc85832011-11-09 08:03:56 +00001198// Find attributes of the memory region that contains ADDR for process PID,
1199// if possible, and return a string describing those attributes.
Jason Molenda1f3966b2011-11-08 04:28:12 +00001200//
Jason Molenda3dc85832011-11-09 08:03:56 +00001201// Returns 1 if we could find attributes for this region and OUTBUF can
1202// be sent to the remote debugger.
Jason Molenda1f3966b2011-11-08 04:28:12 +00001203//
Jason Molenda3dc85832011-11-09 08:03:56 +00001204// Returns 0 if we couldn't find the attributes for a region of memory at
1205// that address and OUTBUF should not be sent.
1206//
1207// Returns -1 if this platform cannot look up information about memory regions
1208// or if we do not yet have a valid launched process.
1209//
Jason Molenda1f3966b2011-11-08 04:28:12 +00001210//----------------------------------------------------------------------
1211int
Greg Claytonfc5dd292011-12-12 18:51:14 +00001212DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info)
Jason Molenda1f3966b2011-11-08 04:28:12 +00001213{
1214 MachProcessSP procSP;
1215 if (GetProcessSP (pid, procSP))
Greg Clayton46fb5582011-11-18 07:03:08 +00001216 return procSP->Task().GetMemoryRegionInfo (addr, region_info);
1217
Jason Molenda1f3966b2011-11-08 04:28:12 +00001218 return -1;
1219}
1220
Han Ming Ong929a94f2012-11-29 22:14:45 +00001221std::string
1222DNBProcessGetProfileData (nub_process_t pid)
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001223{
1224 MachProcessSP procSP;
1225 if (GetProcessSP (pid, procSP))
Han Ming Ong929a94f2012-11-29 22:14:45 +00001226 return procSP->Task().GetProfileData();
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001227
Han Ming Ong929a94f2012-11-29 22:14:45 +00001228 return std::string("");
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001229}
1230
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001231nub_bool_t
Han Ming Ong2abd5ef2013-01-16 00:46:39 +00001232DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec)
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001233{
1234 MachProcessSP procSP;
1235 if (GetProcessSP (pid, procSP))
1236 {
Han Ming Ong2abd5ef2013-01-16 00:46:39 +00001237 procSP->SetEnableAsyncProfiling(enable, interval_usec);
Han Ming Ongab3b8b22012-11-17 00:21:04 +00001238 return true;
1239 }
1240
1241 return false;
1242}
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001243
1244//----------------------------------------------------------------------
1245// Formatted output that uses memory and registers from process and
1246// thread in place of arguments.
1247//----------------------------------------------------------------------
1248nub_size_t
1249DNBPrintf (nub_process_t pid, nub_thread_t tid, nub_addr_t base_addr, FILE *file, const char *format)
1250{
1251 if (file == NULL)
1252 return 0;
1253 enum printf_flags
1254 {
1255 alternate_form = (1 << 0),
1256 zero_padding = (1 << 1),
1257 negative_field_width = (1 << 2),
1258 blank_space = (1 << 3),
1259 show_sign = (1 << 4),
1260 show_thousands_separator= (1 << 5),
1261 };
1262
1263 enum printf_length_modifiers
1264 {
1265 length_mod_h = (1 << 0),
1266 length_mod_hh = (1 << 1),
1267 length_mod_l = (1 << 2),
1268 length_mod_ll = (1 << 3),
1269 length_mod_L = (1 << 4),
1270 length_mod_j = (1 << 5),
1271 length_mod_t = (1 << 6),
1272 length_mod_z = (1 << 7),
1273 length_mod_q = (1 << 8),
1274 };
1275
1276 nub_addr_t addr = base_addr;
1277 char *end_format = (char*)format + strlen(format);
1278 char *end = NULL; // For strtoXXXX calls;
1279 std::basic_string<uint8_t> buf;
1280 nub_size_t total_bytes_read = 0;
1281 DNBDataRef data;
1282 const char *f;
1283 for (f = format; *f != '\0' && f < end_format; f++)
1284 {
1285 char ch = *f;
1286 switch (ch)
1287 {
1288 case '%':
1289 {
1290 f++; // Skip the '%' character
Greg Clayton23f59502012-07-17 03:23:13 +00001291// int min_field_width = 0;
1292// int precision = 0;
1293 //uint32_t flags = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001294 uint32_t length_modifiers = 0;
1295 uint32_t byte_size = 0;
1296 uint32_t actual_byte_size = 0;
1297 bool is_string = false;
1298 bool is_register = false;
1299 DNBRegisterValue register_value;
1300 int64_t register_offset = 0;
1301 nub_addr_t register_addr = INVALID_NUB_ADDRESS;
1302
1303 // Create the format string to use for this conversion specification
1304 // so we can remove and mprintf specific flags and formatters.
1305 std::string fprintf_format("%");
1306
1307 // Decode any flags
1308 switch (*f)
1309 {
Greg Clayton23f59502012-07-17 03:23:13 +00001310 case '#': fprintf_format += *f++; break; //flags |= alternate_form; break;
1311 case '0': fprintf_format += *f++; break; //flags |= zero_padding; break;
1312 case '-': fprintf_format += *f++; break; //flags |= negative_field_width; break;
1313 case ' ': fprintf_format += *f++; break; //flags |= blank_space; break;
1314 case '+': fprintf_format += *f++; break; //flags |= show_sign; break;
1315 case ',': fprintf_format += *f++; break; //flags |= show_thousands_separator;break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001316 case '{':
1317 case '[':
1318 {
1319 // We have a register name specification that can take two forms:
1320 // ${regname} or ${regname+offset}
1321 // The action is to read the register value and add the signed offset
1322 // (if any) and use that as the value to format.
1323 // $[regname] or $[regname+offset]
1324 // The action is to read the register value and add the signed offset
1325 // (if any) and use the result as an address to dereference. The size
1326 // of what is dereferenced is specified by the actual byte size that
1327 // follows the minimum field width and precision (see comments below).
1328 switch (*f)
1329 {
1330 case '{':
1331 case '[':
1332 {
1333 char open_scope_ch = *f;
1334 f++;
1335 const char *reg_name = f;
1336 size_t reg_name_length = strcspn(f, "+-}]");
1337 if (reg_name_length > 0)
1338 {
1339 std::string register_name(reg_name, reg_name_length);
1340 f += reg_name_length;
1341 register_offset = strtoll(f, &end, 0);
1342 if (f < end)
1343 f = end;
1344 if ((open_scope_ch == '{' && *f != '}') || (open_scope_ch == '[' && *f != ']'))
1345 {
1346 fprintf(file, "error: Invalid register format string. Valid formats are %%{regname} or %%{regname+offset}, %%[regname] or %%[regname+offset]\n");
1347 return total_bytes_read;
1348 }
1349 else
1350 {
1351 f++;
1352 if (DNBThreadGetRegisterValueByName(pid, tid, REGISTER_SET_ALL, register_name.c_str(), &register_value))
1353 {
1354 // Set the address to dereference using the register value plus the offset
1355 switch (register_value.info.size)
1356 {
1357 default:
1358 case 0:
1359 fprintf (file, "error: unsupported register size of %u.\n", register_value.info.size);
1360 return total_bytes_read;
1361
1362 case 1: register_addr = register_value.value.uint8 + register_offset; break;
1363 case 2: register_addr = register_value.value.uint16 + register_offset; break;
1364 case 4: register_addr = register_value.value.uint32 + register_offset; break;
1365 case 8: register_addr = register_value.value.uint64 + register_offset; break;
1366 case 16:
1367 if (open_scope_ch == '[')
1368 {
1369 fprintf (file, "error: register size (%u) too large for address.\n", register_value.info.size);
1370 return total_bytes_read;
1371 }
1372 break;
1373 }
1374
1375 if (open_scope_ch == '{')
1376 {
1377 byte_size = register_value.info.size;
1378 is_register = true; // value is in a register
1379
1380 }
1381 else
1382 {
1383 addr = register_addr; // Use register value and offset as the address
1384 }
1385 }
1386 else
1387 {
1388 fprintf(file, "error: unable to read register '%s' for process %#.4x and thread %#.4x\n", register_name.c_str(), pid, tid);
1389 return total_bytes_read;
1390 }
1391 }
1392 }
1393 }
1394 break;
1395
1396 default:
1397 fprintf(file, "error: %%$ must be followed by (regname + n) or [regname + n]\n");
1398 return total_bytes_read;
1399 }
1400 }
1401 break;
1402 }
1403
1404 // Check for a minimum field width
1405 if (isdigit(*f))
1406 {
Greg Clayton23f59502012-07-17 03:23:13 +00001407 //min_field_width = strtoul(f, &end, 10);
1408 strtoul(f, &end, 10);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001409 if (end > f)
1410 {
1411 fprintf_format.append(f, end - f);
1412 f = end;
1413 }
1414 }
1415
1416
1417 // Check for a precision
1418 if (*f == '.')
1419 {
1420 f++;
1421 if (isdigit(*f))
1422 {
1423 fprintf_format += '.';
Greg Clayton23f59502012-07-17 03:23:13 +00001424 //precision = strtoul(f, &end, 10);
1425 strtoul(f, &end, 10);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001426 if (end > f)
1427 {
1428 fprintf_format.append(f, end - f);
1429 f = end;
1430 }
1431 }
1432 }
1433
1434
1435 // mprintf specific: read the optional actual byte size (abs)
1436 // after the standard minimum field width (mfw) and precision (prec).
1437 // Standard printf calls you can have "mfw.prec" or ".prec", but
1438 // mprintf can have "mfw.prec.abs", ".prec.abs" or "..abs". This is nice
1439 // for strings that may be in a fixed size buffer, but may not use all bytes
1440 // in that buffer for printable characters.
1441 if (*f == '.')
1442 {
1443 f++;
1444 actual_byte_size = strtoul(f, &end, 10);
1445 if (end > f)
1446 {
1447 byte_size = actual_byte_size;
1448 f = end;
1449 }
1450 }
1451
1452 // Decode the length modifiers
1453 switch (*f)
1454 {
1455 case 'h': // h and hh length modifiers
1456 fprintf_format += *f++;
1457 length_modifiers |= length_mod_h;
1458 if (*f == 'h')
1459 {
1460 fprintf_format += *f++;
1461 length_modifiers |= length_mod_hh;
1462 }
1463 break;
1464
1465 case 'l': // l and ll length modifiers
1466 fprintf_format += *f++;
1467 length_modifiers |= length_mod_l;
1468 if (*f == 'h')
1469 {
1470 fprintf_format += *f++;
1471 length_modifiers |= length_mod_ll;
1472 }
1473 break;
1474
1475 case 'L': fprintf_format += *f++; length_modifiers |= length_mod_L; break;
1476 case 'j': fprintf_format += *f++; length_modifiers |= length_mod_j; break;
1477 case 't': fprintf_format += *f++; length_modifiers |= length_mod_t; break;
1478 case 'z': fprintf_format += *f++; length_modifiers |= length_mod_z; break;
1479 case 'q': fprintf_format += *f++; length_modifiers |= length_mod_q; break;
1480 }
1481
1482 // Decode the conversion specifier
1483 switch (*f)
1484 {
1485 case '_':
1486 // mprintf specific format items
1487 {
1488 ++f; // Skip the '_' character
1489 switch (*f)
1490 {
1491 case 'a': // Print the current address
1492 ++f;
1493 fprintf_format += "ll";
1494 fprintf_format += *f; // actual format to show address with folows the 'a' ("%_ax")
1495 fprintf (file, fprintf_format.c_str(), addr);
1496 break;
1497 case 'o': // offset from base address
1498 ++f;
1499 fprintf_format += "ll";
1500 fprintf_format += *f; // actual format to show address with folows the 'a' ("%_ox")
1501 fprintf(file, fprintf_format.c_str(), addr - base_addr);
1502 break;
1503 default:
1504 fprintf (file, "error: unsupported mprintf specific format character '%c'.\n", *f);
1505 break;
1506 }
1507 continue;
1508 }
1509 break;
1510
1511 case 'D':
1512 case 'O':
1513 case 'U':
1514 fprintf_format += *f;
1515 if (byte_size == 0)
1516 byte_size = sizeof(long int);
1517 break;
1518
1519 case 'd':
1520 case 'i':
1521 case 'o':
1522 case 'u':
1523 case 'x':
1524 case 'X':
1525 fprintf_format += *f;
1526 if (byte_size == 0)
1527 {
1528 if (length_modifiers & length_mod_hh)
1529 byte_size = sizeof(char);
1530 else if (length_modifiers & length_mod_h)
1531 byte_size = sizeof(short);
Greg Clayton23f59502012-07-17 03:23:13 +00001532 else if (length_modifiers & length_mod_ll)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001533 byte_size = sizeof(long long);
1534 else if (length_modifiers & length_mod_l)
1535 byte_size = sizeof(long);
1536 else
1537 byte_size = sizeof(int);
1538 }
1539 break;
1540
1541 case 'a':
1542 case 'A':
1543 case 'f':
1544 case 'F':
1545 case 'e':
1546 case 'E':
1547 case 'g':
1548 case 'G':
1549 fprintf_format += *f;
1550 if (byte_size == 0)
1551 {
1552 if (length_modifiers & length_mod_L)
1553 byte_size = sizeof(long double);
1554 else
1555 byte_size = sizeof(double);
1556 }
1557 break;
1558
1559 case 'c':
1560 if ((length_modifiers & length_mod_l) == 0)
1561 {
1562 fprintf_format += *f;
1563 if (byte_size == 0)
1564 byte_size = sizeof(char);
1565 break;
1566 }
1567 // Fall through to 'C' modifier below...
1568
1569 case 'C':
1570 fprintf_format += *f;
1571 if (byte_size == 0)
1572 byte_size = sizeof(wchar_t);
1573 break;
1574
1575 case 's':
1576 fprintf_format += *f;
1577 if (is_register || byte_size == 0)
1578 is_string = 1;
1579 break;
1580
1581 case 'p':
1582 fprintf_format += *f;
1583 if (byte_size == 0)
1584 byte_size = sizeof(void*);
1585 break;
1586 }
1587
1588 if (is_string)
1589 {
1590 std::string mem_string;
1591 const size_t string_buf_len = 4;
1592 char string_buf[string_buf_len+1];
1593 char *string_buf_end = string_buf + string_buf_len;
1594 string_buf[string_buf_len] = '\0';
1595 nub_size_t bytes_read;
1596 nub_addr_t str_addr = is_register ? register_addr : addr;
1597 while ((bytes_read = DNBProcessMemoryRead(pid, str_addr, string_buf_len, &string_buf[0])) > 0)
1598 {
1599 // Did we get a NULL termination character yet?
1600 if (strchr(string_buf, '\0') == string_buf_end)
1601 {
1602 // no NULL terminator yet, append as a std::string
1603 mem_string.append(string_buf, string_buf_len);
1604 str_addr += string_buf_len;
1605 }
1606 else
1607 {
1608 // yep
1609 break;
1610 }
1611 }
1612 // Append as a C-string so we don't get the extra NULL
1613 // characters in the temp buffer (since it was resized)
1614 mem_string += string_buf;
1615 size_t mem_string_len = mem_string.size() + 1;
1616 fprintf(file, fprintf_format.c_str(), mem_string.c_str());
1617 if (mem_string_len > 0)
1618 {
1619 if (!is_register)
1620 {
1621 addr += mem_string_len;
1622 total_bytes_read += mem_string_len;
1623 }
1624 }
1625 else
1626 return total_bytes_read;
1627 }
1628 else
1629 if (byte_size > 0)
1630 {
1631 buf.resize(byte_size);
1632 nub_size_t bytes_read = 0;
1633 if (is_register)
1634 bytes_read = register_value.info.size;
1635 else
1636 bytes_read = DNBProcessMemoryRead(pid, addr, buf.size(), &buf[0]);
1637 if (bytes_read > 0)
1638 {
1639 if (!is_register)
1640 total_bytes_read += bytes_read;
1641
1642 if (bytes_read == byte_size)
1643 {
1644 switch (*f)
1645 {
1646 case 'd':
1647 case 'i':
1648 case 'o':
1649 case 'u':
1650 case 'X':
1651 case 'x':
1652 case 'a':
1653 case 'A':
1654 case 'f':
1655 case 'F':
1656 case 'e':
1657 case 'E':
1658 case 'g':
1659 case 'G':
1660 case 'p':
1661 case 'c':
1662 case 'C':
1663 {
1664 if (is_register)
1665 data.SetData(&register_value.value.v_uint8[0], register_value.info.size);
1666 else
1667 data.SetData(&buf[0], bytes_read);
1668 DNBDataRef::offset_t data_offset = 0;
1669 if (byte_size <= 4)
1670 {
1671 uint32_t u32 = data.GetMax32(&data_offset, byte_size);
1672 // Show the actual byte width when displaying hex
1673 fprintf(file, fprintf_format.c_str(), u32);
1674 }
1675 else if (byte_size <= 8)
1676 {
1677 uint64_t u64 = data.GetMax64(&data_offset, byte_size);
1678 // Show the actual byte width when displaying hex
1679 fprintf(file, fprintf_format.c_str(), u64);
1680 }
1681 else
1682 {
1683 fprintf(file, "error: integer size not supported, must be 8 bytes or less (%u bytes).\n", byte_size);
1684 }
1685 if (!is_register)
1686 addr += byte_size;
1687 }
1688 break;
1689
1690 case 's':
1691 fprintf(file, fprintf_format.c_str(), buf.c_str());
1692 addr += byte_size;
1693 break;
1694
1695 default:
1696 fprintf(file, "error: unsupported conversion specifier '%c'.\n", *f);
1697 break;
1698 }
1699 }
1700 }
1701 }
1702 else
1703 return total_bytes_read;
1704 }
1705 break;
1706
1707 case '\\':
1708 {
1709 f++;
1710 switch (*f)
1711 {
1712 case 'e': ch = '\e'; break;
1713 case 'a': ch = '\a'; break;
1714 case 'b': ch = '\b'; break;
1715 case 'f': ch = '\f'; break;
1716 case 'n': ch = '\n'; break;
1717 case 'r': ch = '\r'; break;
1718 case 't': ch = '\t'; break;
1719 case 'v': ch = '\v'; break;
1720 case '\'': ch = '\''; break;
1721 case '\\': ch = '\\'; break;
1722 case '0':
1723 case '1':
1724 case '2':
1725 case '3':
1726 case '4':
1727 case '5':
1728 case '6':
1729 case '7':
1730 ch = strtoul(f, &end, 8);
1731 f = end;
1732 break;
1733 default:
1734 ch = *f;
1735 break;
1736 }
1737 fputc(ch, file);
1738 }
1739 break;
1740
1741 default:
1742 fputc(ch, file);
1743 break;
1744 }
1745 }
1746 return total_bytes_read;
1747}
1748
1749
1750//----------------------------------------------------------------------
1751// Get the number of threads for the specified process.
1752//----------------------------------------------------------------------
1753nub_size_t
1754DNBProcessGetNumThreads (nub_process_t pid)
1755{
1756 MachProcessSP procSP;
1757 if (GetProcessSP (pid, procSP))
1758 return procSP->GetNumThreads();
1759 return 0;
1760}
1761
1762//----------------------------------------------------------------------
1763// Get the thread ID of the current thread.
1764//----------------------------------------------------------------------
1765nub_thread_t
1766DNBProcessGetCurrentThread (nub_process_t pid)
1767{
1768 MachProcessSP procSP;
1769 if (GetProcessSP (pid, procSP))
1770 return procSP->GetCurrentThread();
1771 return 0;
1772}
1773
1774//----------------------------------------------------------------------
1775// Change the current thread.
1776//----------------------------------------------------------------------
1777nub_thread_t
1778DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid)
1779{
1780 MachProcessSP procSP;
1781 if (GetProcessSP (pid, procSP))
1782 return procSP->SetCurrentThread (tid);
1783 return INVALID_NUB_THREAD;
1784}
1785
1786
1787//----------------------------------------------------------------------
1788// Dump a string describing a thread's stop reason to the specified file
1789// handle
1790//----------------------------------------------------------------------
1791nub_bool_t
1792DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
1793{
1794 MachProcessSP procSP;
1795 if (GetProcessSP (pid, procSP))
1796 return procSP->GetThreadStoppedReason (tid, stop_info);
1797 return false;
1798}
1799
1800//----------------------------------------------------------------------
1801// Return string description for the specified thread.
1802//
1803// RETURNS: NULL if the thread isn't valid, else a NULL terminated C
1804// string from a static buffer that must be copied prior to subsequent
1805// calls.
1806//----------------------------------------------------------------------
1807const char *
1808DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid)
1809{
1810 MachProcessSP procSP;
1811 if (GetProcessSP (pid, procSP))
1812 return procSP->GetThreadInfo (tid);
1813 return NULL;
1814}
1815
1816//----------------------------------------------------------------------
1817// Get the thread ID given a thread index.
1818//----------------------------------------------------------------------
1819nub_thread_t
1820DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx)
1821{
1822 MachProcessSP procSP;
1823 if (GetProcessSP (pid, procSP))
1824 return procSP->GetThreadAtIndex (thread_idx);
1825 return INVALID_NUB_THREAD;
1826}
1827
Jim Ingham279ceec2012-07-25 21:12:43 +00001828//----------------------------------------------------------------------
1829// Do whatever is needed to sync the thread's register state with it's kernel values.
1830//----------------------------------------------------------------------
1831nub_bool_t
1832DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid)
1833{
1834 MachProcessSP procSP;
1835 if (GetProcessSP (pid, procSP))
1836 return procSP->SyncThreadState (tid);
1837 return false;
1838
1839}
1840
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001841nub_addr_t
1842DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid)
1843{
1844 MachProcessSP procSP;
1845 DNBError err;
1846 if (GetProcessSP (pid, procSP))
1847 return procSP->Task().GetDYLDAllImageInfosAddress (err);
1848 return INVALID_NUB_ADDRESS;
1849}
1850
1851
1852nub_bool_t
1853DNBProcessSharedLibrariesUpdated(nub_process_t pid)
1854{
1855 MachProcessSP procSP;
1856 if (GetProcessSP (pid, procSP))
1857 {
1858 procSP->SharedLibrariesUpdated ();
1859 return true;
1860 }
1861 return false;
1862}
1863
1864//----------------------------------------------------------------------
1865// Get the current shared library information for a process. Only return
1866// the shared libraries that have changed since the last shared library
1867// state changed event if only_changed is non-zero.
1868//----------------------------------------------------------------------
1869nub_size_t
1870DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos)
1871{
1872 MachProcessSP procSP;
1873 if (GetProcessSP (pid, procSP))
1874 return procSP->CopyImageInfos (image_infos, only_changed);
1875
1876 // If we have no process, then return NULL for the shared library info
1877 // and zero for shared library count
1878 *image_infos = NULL;
1879 return 0;
1880}
1881
1882//----------------------------------------------------------------------
1883// Get the register set information for a specific thread.
1884//----------------------------------------------------------------------
1885const DNBRegisterSetInfo *
1886DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
1887{
Greg Clayton3af9ea52010-11-18 05:57:03 +00001888 return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001889}
1890
1891
1892//----------------------------------------------------------------------
1893// Read a register value by register set and register index.
1894//----------------------------------------------------------------------
1895nub_bool_t
1896DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value)
1897{
1898 MachProcessSP procSP;
1899 ::bzero (value, sizeof(DNBRegisterValue));
1900 if (GetProcessSP (pid, procSP))
1901 {
1902 if (tid != INVALID_NUB_THREAD)
1903 return procSP->GetRegisterValue (tid, set, reg, value);
1904 }
1905 return false;
1906}
1907
1908nub_bool_t
1909DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value)
1910{
1911 if (tid != INVALID_NUB_THREAD)
1912 {
1913 MachProcessSP procSP;
1914 if (GetProcessSP (pid, procSP))
1915 return procSP->SetRegisterValue (tid, set, reg, value);
1916 }
1917 return false;
1918}
1919
1920nub_size_t
1921DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len)
1922{
1923 MachProcessSP procSP;
1924 if (GetProcessSP (pid, procSP))
1925 {
1926 if (tid != INVALID_NUB_THREAD)
1927 return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len);
1928 }
1929 ::bzero (buf, buf_len);
1930 return 0;
1931
1932}
1933
1934nub_size_t
1935DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len)
1936{
1937 MachProcessSP procSP;
1938 if (GetProcessSP (pid, procSP))
1939 {
1940 if (tid != INVALID_NUB_THREAD)
1941 return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len);
1942 }
1943 return 0;
1944}
1945
1946//----------------------------------------------------------------------
1947// Read a register value by name.
1948//----------------------------------------------------------------------
1949nub_bool_t
1950DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value)
1951{
1952 MachProcessSP procSP;
1953 ::bzero (value, sizeof(DNBRegisterValue));
1954 if (GetProcessSP (pid, procSP))
1955 {
1956 const struct DNBRegisterSetInfo *set_info;
1957 nub_size_t num_reg_sets = 0;
1958 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1959 if (set_info)
1960 {
1961 uint32_t set = reg_set;
1962 uint32_t reg;
1963 if (set == REGISTER_SET_ALL)
1964 {
1965 for (set = 1; set < num_reg_sets; ++set)
1966 {
1967 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1968 {
1969 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1970 return procSP->GetRegisterValue (tid, set, reg, value);
1971 }
1972 }
1973 }
1974 else
1975 {
1976 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1977 {
1978 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1979 return procSP->GetRegisterValue (tid, set, reg, value);
1980 }
1981 }
1982 }
1983 }
1984 return false;
1985}
1986
1987
1988//----------------------------------------------------------------------
1989// Read a register set and register number from the register name.
1990//----------------------------------------------------------------------
1991nub_bool_t
1992DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info)
1993{
1994 const struct DNBRegisterSetInfo *set_info;
1995 nub_size_t num_reg_sets = 0;
1996 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1997 if (set_info)
1998 {
1999 uint32_t set, reg;
2000 for (set = 1; set < num_reg_sets; ++set)
2001 {
2002 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2003 {
2004 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
2005 {
2006 *info = set_info[set].registers[reg];
2007 return true;
2008 }
2009 }
2010 }
2011
2012 for (set = 1; set < num_reg_sets; ++set)
2013 {
2014 uint32_t reg;
2015 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2016 {
2017 if (set_info[set].registers[reg].alt == NULL)
2018 continue;
2019
2020 if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0)
2021 {
2022 *info = set_info[set].registers[reg];
2023 return true;
2024 }
2025 }
2026 }
2027 }
2028
2029 ::bzero (info, sizeof(DNBRegisterInfo));
2030 return false;
2031}
2032
2033
2034//----------------------------------------------------------------------
2035// Set the name to address callback function that this nub can use
2036// for any name to address lookups that are needed.
2037//----------------------------------------------------------------------
2038nub_bool_t
2039DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton)
2040{
2041 MachProcessSP procSP;
2042 if (GetProcessSP (pid, procSP))
2043 {
2044 procSP->SetNameToAddressCallback (callback, baton);
2045 return true;
2046 }
2047 return false;
2048}
2049
2050
2051//----------------------------------------------------------------------
2052// Set the name to address callback function that this nub can use
2053// for any name to address lookups that are needed.
2054//----------------------------------------------------------------------
2055nub_bool_t
2056DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton)
2057{
2058 MachProcessSP procSP;
2059 if (GetProcessSP (pid, procSP))
2060 {
2061 procSP->SetSharedLibraryInfoCallback (callback, baton);
2062 return true;
2063 }
2064 return false;
2065}
2066
2067nub_addr_t
2068DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib)
2069{
2070 MachProcessSP procSP;
2071 if (GetProcessSP (pid, procSP))
2072 {
2073 return procSP->LookupSymbol (name, shlib);
2074 }
2075 return INVALID_NUB_ADDRESS;
2076}
2077
2078
2079nub_size_t
2080DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size)
2081{
2082 MachProcessSP procSP;
2083 if (GetProcessSP (pid, procSP))
2084 return procSP->GetAvailableSTDOUT (buf, buf_size);
2085 return 0;
2086}
2087
2088nub_size_t
2089DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size)
2090{
2091 MachProcessSP procSP;
2092 if (GetProcessSP (pid, procSP))
2093 return procSP->GetAvailableSTDERR (buf, buf_size);
2094 return 0;
2095}
2096
2097nub_size_t
Han Ming Ongab3b8b22012-11-17 00:21:04 +00002098DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size)
2099{
2100 MachProcessSP procSP;
2101 if (GetProcessSP (pid, procSP))
2102 return procSP->GetAsyncProfileData (buf, buf_size);
2103 return 0;
2104}
2105
2106nub_size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002107DNBProcessGetStopCount (nub_process_t pid)
2108{
2109 MachProcessSP procSP;
2110 if (GetProcessSP (pid, procSP))
2111 return procSP->StopCount();
2112 return 0;
2113}
2114
Greg Clayton71337622011-02-24 22:24:29 +00002115uint32_t
2116DNBProcessGetCPUType (nub_process_t pid)
2117{
2118 MachProcessSP procSP;
2119 if (GetProcessSP (pid, procSP))
2120 return procSP->GetCPUType ();
2121 return 0;
2122
2123}
2124
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002125nub_bool_t
2126DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
2127{
2128 if (path == NULL || path[0] == '\0')
2129 return false;
2130
2131 char max_path[PATH_MAX];
2132 std::string result;
2133 CFString::GlobPath(path, result);
2134
2135 if (result.empty())
2136 result = path;
Greg Clayton48baf7a2012-10-31 21:44:39 +00002137
2138 struct stat path_stat;
2139 if (::stat(path, &path_stat) == 0)
2140 {
2141 if ((path_stat.st_mode & S_IFMT) == S_IFDIR)
2142 {
2143 CFBundle bundle (path);
2144 CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
2145 if (url.get())
2146 {
2147 if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size))
2148 return true;
2149 }
2150 }
2151 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002152
2153 if (realpath(path, max_path))
2154 {
2155 // Found the path relatively...
2156 ::strncpy(resolved_path, max_path, resolved_path_size);
2157 return strlen(resolved_path) + 1 < resolved_path_size;
2158 }
2159 else
2160 {
2161 // Not a relative path, check the PATH environment variable if the
2162 const char *PATH = getenv("PATH");
2163 if (PATH)
2164 {
2165 const char *curr_path_start = PATH;
2166 const char *curr_path_end;
2167 while (curr_path_start && *curr_path_start)
2168 {
2169 curr_path_end = strchr(curr_path_start, ':');
2170 if (curr_path_end == NULL)
2171 {
2172 result.assign(curr_path_start);
2173 curr_path_start = NULL;
2174 }
2175 else if (curr_path_end > curr_path_start)
2176 {
2177 size_t len = curr_path_end - curr_path_start;
2178 result.assign(curr_path_start, len);
2179 curr_path_start += len + 1;
2180 }
2181 else
2182 break;
2183
2184 result += '/';
2185 result += path;
2186 struct stat s;
2187 if (stat(result.c_str(), &s) == 0)
2188 {
2189 ::strncpy(resolved_path, result.c_str(), resolved_path_size);
2190 return result.size() + 1 < resolved_path_size;
2191 }
2192 }
2193 }
2194 }
2195 return false;
2196}
2197
Greg Clayton3af9ea52010-11-18 05:57:03 +00002198
2199void
2200DNBInitialize()
2201{
2202 DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
2203#if defined (__i386__) || defined (__x86_64__)
2204 DNBArchImplI386::Initialize();
2205 DNBArchImplX86_64::Initialize();
2206#elif defined (__arm__)
2207 DNBArchMachARM::Initialize();
2208#endif
2209}
2210
2211void
2212DNBTerminate()
2213{
2214}
Greg Clayton3c144382010-12-01 22:45:40 +00002215
2216nub_bool_t
2217DNBSetArchitecture (const char *arch)
2218{
2219 if (arch && arch[0])
2220 {
2221 if (strcasecmp (arch, "i386") == 0)
2222 return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386);
2223 else if (strcasecmp (arch, "x86_64") == 0)
2224 return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64);
2225 else if (strstr (arch, "arm") == arch)
2226 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM);
2227 }
2228 return false;
2229}