[Lldb-commits] [lldb] r280751 - *** This commit represents a complete reformatting of the LLDB source code
Kate Stone via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 6 13:58:36 PDT 2016
Modified: lldb/trunk/tools/debugserver/source/DNB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNB.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNB.cpp (original)
+++ lldb/trunk/tools/debugserver/source/DNB.cpp Tue Sep 6 15:57:50 2016
@@ -13,20 +13,20 @@
#include "DNB.h"
#include <inttypes.h>
+#include <libproc.h>
+#include <map>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <sys/stat.h>
+#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
-#include <sys/sysctl.h>
-#include <map>
#include <vector>
-#include <libproc.h>
-#if defined (__APPLE__)
+#if defined(__APPLE__)
#include <pthread.h>
#include <sched.h>
#endif
@@ -34,33 +34,34 @@
#define TRY_KQUEUE 1
#ifdef TRY_KQUEUE
- #include <sys/event.h>
- #include <sys/time.h>
- #ifdef NOTE_EXIT_DETAIL
- #define USE_KQUEUE
- #endif
+#include <sys/event.h>
+#include <sys/time.h>
+#ifdef NOTE_EXIT_DETAIL
+#define USE_KQUEUE
+#endif
#endif
-#include "MacOSX/DarwinLog/DarwinLogCollector.h"
-#include "MacOSX/MachProcess.h"
-#include "MacOSX/MachTask.h"
-#include "MacOSX/Genealogy.h"
-#include "MacOSX/ThreadInfo.h"
+#include "CFBundle.h"
#include "CFString.h"
-#include "DNBLog.h"
#include "DNBDataRef.h"
+#include "DNBLog.h"
#include "DNBThreadResumeActions.h"
#include "DNBTimer.h"
-#include "CFBundle.h"
-
+#include "MacOSX/DarwinLog/DarwinLogCollector.h"
+#include "MacOSX/Genealogy.h"
+#include "MacOSX/MachProcess.h"
+#include "MacOSX/MachTask.h"
+#include "MacOSX/ThreadInfo.h"
typedef std::shared_ptr<MachProcess> MachProcessSP;
typedef std::map<nub_process_t, MachProcessSP> ProcessMap;
typedef ProcessMap::iterator ProcessMapIter;
typedef ProcessMap::const_iterator ProcessMapConstIter;
-size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos);
-static size_t GetAllInfosMatchingName (const char *process_name, std::vector<struct kinfo_proc>& matching_proc_infos);
+size_t GetAllInfos(std::vector<struct kinfo_proc> &proc_infos);
+static size_t
+GetAllInfosMatchingName(const char *process_name,
+ std::vector<struct kinfo_proc> &matching_proc_infos);
//----------------------------------------------------------------------
// A Thread safe singleton to get a process map pointer.
@@ -68,19 +69,16 @@ static size_t GetAllInfosMatchingName (c
// Returns a pointer to the existing process map, or a pointer to a
// newly created process map if CAN_CREATE is non-zero.
//----------------------------------------------------------------------
-static ProcessMap*
-GetProcessMap(bool can_create)
-{
- static ProcessMap* g_process_map_ptr = NULL;
-
- if (can_create && g_process_map_ptr == NULL)
- {
- static pthread_mutex_t g_process_map_mutex = PTHREAD_MUTEX_INITIALIZER;
- PTHREAD_MUTEX_LOCKER (locker, &g_process_map_mutex);
- if (g_process_map_ptr == NULL)
- g_process_map_ptr = new ProcessMap;
- }
- return g_process_map_ptr;
+static ProcessMap *GetProcessMap(bool can_create) {
+ static ProcessMap *g_process_map_ptr = NULL;
+
+ if (can_create && g_process_map_ptr == NULL) {
+ static pthread_mutex_t g_process_map_mutex = PTHREAD_MUTEX_INITIALIZER;
+ PTHREAD_MUTEX_LOCKER(locker, &g_process_map_mutex);
+ if (g_process_map_ptr == NULL)
+ g_process_map_ptr = new ProcessMap;
+ }
+ return g_process_map_ptr;
}
//----------------------------------------------------------------------
@@ -90,16 +88,13 @@ GetProcessMap(bool can_create)
// The only time this should fail is if we run out of memory and can't
// allocate a ProcessMap.
//----------------------------------------------------------------------
-static nub_bool_t
-AddProcessToMap (nub_process_t pid, MachProcessSP& procSP)
-{
- ProcessMap* process_map = GetProcessMap(true);
- if (process_map)
- {
- process_map->insert(std::make_pair(pid, procSP));
- return true;
- }
- return false;
+static nub_bool_t AddProcessToMap(nub_process_t pid, MachProcessSP &procSP) {
+ ProcessMap *process_map = GetProcessMap(true);
+ if (process_map) {
+ process_map->insert(std::make_pair(pid, procSP));
+ return true;
+ }
+ return false;
}
//----------------------------------------------------------------------
@@ -107,8 +102,8 @@ AddProcessToMap (nub_process_t pid, Mach
//
// Returns the number of items removed from the process map.
//----------------------------------------------------------------------
-//static size_t
-//RemoveProcessFromMap (nub_process_t pid)
+// static size_t
+// RemoveProcessFromMap (nub_process_t pid)
//{
// ProcessMap* process_map = GetProcessMap(false);
// if (process_map)
@@ -124,1079 +119,958 @@ AddProcessToMap (nub_process_t pid, Mach
// Returns true if we successfully find a shared pointer to a
// MachProcess object.
//----------------------------------------------------------------------
-static nub_bool_t
-GetProcessSP (nub_process_t pid, MachProcessSP& procSP)
-{
- ProcessMap* process_map = GetProcessMap(false);
- if (process_map != NULL)
- {
- ProcessMapIter pos = process_map->find(pid);
- if (pos != process_map->end())
- {
- procSP = pos->second;
- return true;
- }
- }
- procSP.reset();
- return false;
+static nub_bool_t GetProcessSP(nub_process_t pid, MachProcessSP &procSP) {
+ ProcessMap *process_map = GetProcessMap(false);
+ if (process_map != NULL) {
+ ProcessMapIter pos = process_map->find(pid);
+ if (pos != process_map->end()) {
+ procSP = pos->second;
+ return true;
+ }
+ }
+ procSP.reset();
+ return false;
}
#ifdef USE_KQUEUE
-void *
-kqueue_thread (void *arg)
-{
- int kq_id = (int) (intptr_t) arg;
-
-#if defined (__APPLE__)
- pthread_setname_np ("kqueue thread");
-#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
- struct sched_param thread_param;
- int thread_sched_policy;
- if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0)
- {
- thread_param.sched_priority = 47;
- pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
- }
+void *kqueue_thread(void *arg) {
+ int kq_id = (int)(intptr_t)arg;
+
+#if defined(__APPLE__)
+ pthread_setname_np("kqueue thread");
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+ struct sched_param thread_param;
+ int thread_sched_policy;
+ if (pthread_getschedparam(pthread_self(), &thread_sched_policy,
+ &thread_param) == 0) {
+ thread_param.sched_priority = 47;
+ pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
+ }
#endif
#endif
- struct kevent death_event;
- while (1)
- {
- int n_events = kevent (kq_id, NULL, 0, &death_event, 1, NULL);
- if (n_events == -1)
- {
- if (errno == EINTR)
- continue;
- else
- {
- DNBLogError ("kqueue failed with error: (%d): %s", errno, strerror(errno));
- return NULL;
- }
- }
- else if (death_event.flags & EV_ERROR)
- {
- int error_no = static_cast<int>(death_event.data);
- const char *error_str = strerror(error_no);
- if (error_str == NULL)
- error_str = "Unknown error";
- DNBLogError ("Failed to initialize kqueue event: (%d): %s", error_no, error_str );
- return NULL;
- }
- else
- {
- int status;
- const pid_t pid = (pid_t)death_event.ident;
- const pid_t child_pid = waitpid (pid, &status, 0);
-
-
- bool exited = false;
- int signal = 0;
- int exit_status = 0;
- if (WIFSTOPPED(status))
- {
- signal = WSTOPSIG(status);
- DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)", child_pid, signal);
- }
- else if (WIFEXITED(status))
- {
- exit_status = WEXITSTATUS(status);
- exited = true;
- DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)", child_pid, exit_status);
- }
- else if (WIFSIGNALED(status))
- {
- signal = WTERMSIG(status);
- if (child_pid == abs(pid))
- {
- DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED and EXITED (signal = %i)", child_pid, signal);
- char exit_info[64];
- ::snprintf (exit_info, sizeof(exit_info), "Terminated due to signal %i", signal);
- DNBProcessSetExitInfo (child_pid, exit_info);
- exited = true;
- exit_status = INT8_MAX;
- }
- else
- {
- DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED (signal = %i)", child_pid, signal);
- }
- }
-
- if (exited)
- {
- if (death_event.data & NOTE_EXIT_MEMORY)
- DNBProcessSetExitInfo (child_pid, "Terminated due to memory issue");
- else if (death_event.data & NOTE_EXIT_DECRYPTFAIL)
- DNBProcessSetExitInfo (child_pid, "Terminated due to decrypt failure");
- else if (death_event.data & NOTE_EXIT_CSERROR)
- DNBProcessSetExitInfo (child_pid, "Terminated due to code signing error");
-
- DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, exit_status);
- DNBProcessSetExitStatus (child_pid, status);
- return NULL;
- }
- }
- }
-}
-
-static bool
-spawn_kqueue_thread (pid_t pid)
-{
- pthread_t thread;
- int kq_id;
-
- kq_id = kqueue();
- if (kq_id == -1)
- {
- DNBLogError ("Could not get kqueue for pid = %i.", pid);
- return false;
- }
-
- struct kevent reg_event;
-
- EV_SET(®_event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT|NOTE_EXITSTATUS|NOTE_EXIT_DETAIL, 0, NULL);
- // Register the event:
- int result = kevent (kq_id, ®_event, 1, NULL, 0, NULL);
- if (result != 0)
- {
- DNBLogError ("Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, result);
- return false;
- }
-
- int ret = ::pthread_create (&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id);
-
- // pthread_create returns 0 if successful
- if (ret == 0)
- {
- ::pthread_detach (thread);
- return true;
- }
- return false;
+ struct kevent death_event;
+ while (1) {
+ int n_events = kevent(kq_id, NULL, 0, &death_event, 1, NULL);
+ if (n_events == -1) {
+ if (errno == EINTR)
+ continue;
+ else {
+ DNBLogError("kqueue failed with error: (%d): %s", errno,
+ strerror(errno));
+ return NULL;
+ }
+ } else if (death_event.flags & EV_ERROR) {
+ int error_no = static_cast<int>(death_event.data);
+ const char *error_str = strerror(error_no);
+ if (error_str == NULL)
+ error_str = "Unknown error";
+ DNBLogError("Failed to initialize kqueue event: (%d): %s", error_no,
+ error_str);
+ return NULL;
+ } else {
+ int status;
+ const pid_t pid = (pid_t)death_event.ident;
+ const pid_t child_pid = waitpid(pid, &status, 0);
+
+ bool exited = false;
+ int signal = 0;
+ int exit_status = 0;
+ if (WIFSTOPPED(status)) {
+ signal = WSTOPSIG(status);
+ DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)",
+ child_pid, signal);
+ } else if (WIFEXITED(status)) {
+ exit_status = WEXITSTATUS(status);
+ exited = true;
+ DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)",
+ child_pid, exit_status);
+ } else if (WIFSIGNALED(status)) {
+ signal = WTERMSIG(status);
+ if (child_pid == abs(pid)) {
+ DNBLogThreadedIf(LOG_PROCESS,
+ "waitpid (%i) -> SIGNALED and EXITED (signal = %i)",
+ child_pid, signal);
+ char exit_info[64];
+ ::snprintf(exit_info, sizeof(exit_info),
+ "Terminated due to signal %i", signal);
+ DNBProcessSetExitInfo(child_pid, exit_info);
+ exited = true;
+ exit_status = INT8_MAX;
+ } else {
+ DNBLogThreadedIf(LOG_PROCESS,
+ "waitpid (%i) -> SIGNALED (signal = %i)", child_pid,
+ signal);
+ }
+ }
+
+ if (exited) {
+ if (death_event.data & NOTE_EXIT_MEMORY)
+ DNBProcessSetExitInfo(child_pid, "Terminated due to memory issue");
+ else if (death_event.data & NOTE_EXIT_DECRYPTFAIL)
+ DNBProcessSetExitInfo(child_pid, "Terminated due to decrypt failure");
+ else if (death_event.data & NOTE_EXIT_CSERROR)
+ DNBProcessSetExitInfo(child_pid,
+ "Terminated due to code signing error");
+
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "waitpid_process_thread (): setting exit status for pid = %i to %i",
+ child_pid, exit_status);
+ DNBProcessSetExitStatus(child_pid, status);
+ return NULL;
+ }
+ }
+ }
+}
+
+static bool spawn_kqueue_thread(pid_t pid) {
+ pthread_t thread;
+ int kq_id;
+
+ kq_id = kqueue();
+ if (kq_id == -1) {
+ DNBLogError("Could not get kqueue for pid = %i.", pid);
+ return false;
+ }
+
+ struct kevent reg_event;
+
+ EV_SET(®_event, pid, EVFILT_PROC, EV_ADD,
+ NOTE_EXIT | NOTE_EXITSTATUS | NOTE_EXIT_DETAIL, 0, NULL);
+ // Register the event:
+ int result = kevent(kq_id, ®_event, 1, NULL, 0, NULL);
+ if (result != 0) {
+ DNBLogError(
+ "Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid,
+ result);
+ return false;
+ }
+
+ int ret =
+ ::pthread_create(&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id);
+
+ // pthread_create returns 0 if successful
+ if (ret == 0) {
+ ::pthread_detach(thread);
+ return true;
+ }
+ return false;
}
#endif // #if USE_KQUEUE
-static void *
-waitpid_thread (void *arg)
-{
- const pid_t pid = (pid_t)(intptr_t)arg;
- int status;
-
-#if defined (__APPLE__)
- pthread_setname_np ("waitpid thread");
-#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
- struct sched_param thread_param;
- int thread_sched_policy;
- if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0)
- {
- thread_param.sched_priority = 47;
- pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
- }
+static void *waitpid_thread(void *arg) {
+ const pid_t pid = (pid_t)(intptr_t)arg;
+ int status;
+
+#if defined(__APPLE__)
+ pthread_setname_np("waitpid thread");
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+ struct sched_param thread_param;
+ int thread_sched_policy;
+ if (pthread_getschedparam(pthread_self(), &thread_sched_policy,
+ &thread_param) == 0) {
+ thread_param.sched_priority = 47;
+ pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
+ }
#endif
#endif
- while (1)
- {
- pid_t child_pid = waitpid(pid, &status, 0);
- DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): waitpid (pid = %i, &status, 0) => %i, status = %i, errno = %i", pid, child_pid, status, errno);
-
- if (child_pid < 0)
- {
- if (errno == EINTR)
- continue;
- break;
- }
- else
- {
- if (WIFSTOPPED(status))
- {
- continue;
- }
- else// if (WIFEXITED(status) || WIFSIGNALED(status))
- {
- DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): setting exit status for pid = %i to %i", child_pid, status);
- DNBProcessSetExitStatus (child_pid, status);
- return NULL;
- }
- }
- }
-
- // We should never exit as long as our child process is alive, so if we
- // do something else went wrong and we should exit...
- DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): main loop exited, setting exit status to an invalid value (-1) for pid %i", pid);
- DNBProcessSetExitStatus (pid, -1);
- return NULL;
-}
-static bool
-spawn_waitpid_thread (pid_t pid)
-{
+ while (1) {
+ pid_t child_pid = waitpid(pid, &status, 0);
+ DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): waitpid (pid = %i, "
+ "&status, 0) => %i, status = %i, errno = %i",
+ pid, child_pid, status, errno);
+
+ if (child_pid < 0) {
+ if (errno == EINTR)
+ continue;
+ break;
+ } else {
+ if (WIFSTOPPED(status)) {
+ continue;
+ } else // if (WIFEXITED(status) || WIFSIGNALED(status))
+ {
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "waitpid_thread (): setting exit status for pid = %i to %i",
+ child_pid, status);
+ DNBProcessSetExitStatus(child_pid, status);
+ return NULL;
+ }
+ }
+ }
+
+ // We should never exit as long as our child process is alive, so if we
+ // do something else went wrong and we should exit...
+ DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): main loop exited, setting "
+ "exit status to an invalid value (-1) for pid "
+ "%i",
+ pid);
+ DNBProcessSetExitStatus(pid, -1);
+ return NULL;
+}
+static bool spawn_waitpid_thread(pid_t pid) {
#ifdef USE_KQUEUE
- bool success = spawn_kqueue_thread (pid);
- if (success)
- return true;
+ bool success = spawn_kqueue_thread(pid);
+ if (success)
+ return true;
#endif
- pthread_t thread;
- int ret = ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid);
- // pthread_create returns 0 if successful
- if (ret == 0)
- {
- ::pthread_detach (thread);
- return true;
- }
- return false;
-}
-
-nub_process_t
-DNBProcessLaunch (const char *path,
- char const *argv[],
- const char *envp[],
- const char *working_directory, // NULL => don't change, non-NULL => set working directory for inferior to this
- const char *stdin_path,
- const char *stdout_path,
- const char *stderr_path,
- bool no_stdio,
- nub_launch_flavor_t launch_flavor,
- int disable_aslr,
- const char *event_data,
- char *err_str,
- size_t err_len)
-{
- 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...",
- __FUNCTION__, path, static_cast<void *>(argv), static_cast<void *>(envp), working_directory,
- stdin_path, stdout_path, stderr_path, no_stdio, launch_flavor, disable_aslr,
- static_cast<void *>(err_str), static_cast<uint64_t>(err_len));
-
- if (err_str && err_len > 0)
- err_str[0] = '\0';
- struct stat path_stat;
- if (::stat(path, &path_stat) == -1)
- {
- char stat_error[256];
- ::strerror_r (errno, stat_error, sizeof(stat_error));
- snprintf(err_str, err_len, "%s (%s)", stat_error, path);
- return INVALID_NUB_PROCESS;
- }
-
- MachProcessSP processSP (new MachProcess);
- if (processSP.get())
- {
- DNBError launch_err;
- pid_t pid = processSP->LaunchForDebug (path,
- argv,
- envp,
- working_directory,
- stdin_path,
- stdout_path,
- stderr_path,
- no_stdio,
- launch_flavor,
- disable_aslr,
- event_data,
- launch_err);
- if (err_str)
- {
- *err_str = '\0';
- if (launch_err.Fail())
- {
- const char *launch_err_str = launch_err.AsString();
- if (launch_err_str)
- {
- strncpy(err_str, launch_err_str, err_len-1);
- err_str[err_len-1] = '\0'; // Make sure the error string is terminated
- }
- }
- }
-
- DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
+ pthread_t thread;
+ int ret =
+ ::pthread_create(&thread, NULL, waitpid_thread, (void *)(intptr_t)pid);
+ // pthread_create returns 0 if successful
+ if (ret == 0) {
+ ::pthread_detach(thread);
+ return true;
+ }
+ return false;
+}
+
+nub_process_t DNBProcessLaunch(
+ const char *path, char const *argv[], const char *envp[],
+ const char *working_directory, // NULL => don't change, non-NULL => set
+ // working directory for inferior to this
+ const char *stdin_path, const char *stdout_path, const char *stderr_path,
+ bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr,
+ const char *event_data, char *err_str, size_t err_len) {
+ 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...",
+ __FUNCTION__, path, static_cast<void *>(argv),
+ static_cast<void *>(envp), working_directory, stdin_path,
+ stdout_path, stderr_path, no_stdio, launch_flavor,
+ disable_aslr, static_cast<void *>(err_str),
+ static_cast<uint64_t>(err_len));
+
+ if (err_str && err_len > 0)
+ err_str[0] = '\0';
+ struct stat path_stat;
+ if (::stat(path, &path_stat) == -1) {
+ char stat_error[256];
+ ::strerror_r(errno, stat_error, sizeof(stat_error));
+ snprintf(err_str, err_len, "%s (%s)", stat_error, path);
+ return INVALID_NUB_PROCESS;
+ }
- if (pid != INVALID_NUB_PROCESS)
- {
- // Spawn a thread to reap our child inferior process...
- spawn_waitpid_thread (pid);
-
- if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL)
- {
- // We failed to get the task for our process ID which is bad.
- // Kill our process otherwise it will be stopped at the entry
- // point and get reparented to someone else and never go away.
- DNBLog ("Could not get task port for process, sending SIGKILL and exiting.");
- kill (SIGKILL, pid);
-
- if (err_str && err_len > 0)
- {
- if (launch_err.AsString())
- {
- ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString());
- }
- else
- {
- ::snprintf (err_str, err_len, "failed to get the task for process %i", pid);
- }
- }
- }
- else
- {
- bool res = AddProcessToMap(pid, processSP);
- UNUSED_IF_ASSERT_DISABLED(res);
- assert(res && "Couldn't add process to map!");
- return pid;
- }
- }
+ MachProcessSP processSP(new MachProcess);
+ if (processSP.get()) {
+ DNBError launch_err;
+ pid_t pid = processSP->LaunchForDebug(path, argv, envp, working_directory,
+ stdin_path, stdout_path, stderr_path,
+ no_stdio, launch_flavor, disable_aslr,
+ event_data, launch_err);
+ if (err_str) {
+ *err_str = '\0';
+ if (launch_err.Fail()) {
+ const char *launch_err_str = launch_err.AsString();
+ if (launch_err_str) {
+ strncpy(err_str, launch_err_str, err_len - 1);
+ err_str[err_len - 1] =
+ '\0'; // Make sure the error string is terminated
+ }
+ }
+ }
+
+ DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
+
+ if (pid != INVALID_NUB_PROCESS) {
+ // Spawn a thread to reap our child inferior process...
+ spawn_waitpid_thread(pid);
+
+ if (processSP->Task().TaskPortForProcessID(launch_err) == TASK_NULL) {
+ // We failed to get the task for our process ID which is bad.
+ // Kill our process otherwise it will be stopped at the entry
+ // point and get reparented to someone else and never go away.
+ DNBLog("Could not get task port for process, sending SIGKILL and "
+ "exiting.");
+ kill(SIGKILL, pid);
+
+ if (err_str && err_len > 0) {
+ if (launch_err.AsString()) {
+ ::snprintf(err_str, err_len,
+ "failed to get the task for process %i (%s)", pid,
+ launch_err.AsString());
+ } else {
+ ::snprintf(err_str, err_len,
+ "failed to get the task for process %i", pid);
+ }
+ }
+ } else {
+ bool res = AddProcessToMap(pid, processSP);
+ UNUSED_IF_ASSERT_DISABLED(res);
+ assert(res && "Couldn't add process to map!");
+ return pid;
+ }
}
- return INVALID_NUB_PROCESS;
+ }
+ return INVALID_NUB_PROCESS;
}
// If there is one process with a given name, return the pid for that process.
-nub_process_t
-DNBProcessGetPIDByName (const char *name)
-{
- std::vector<struct kinfo_proc> matching_proc_infos;
- size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
- if (num_matching_proc_infos == 1)
- {
- return matching_proc_infos[0].kp_proc.p_pid;
- }
+nub_process_t DNBProcessGetPIDByName(const char *name) {
+ std::vector<struct kinfo_proc> matching_proc_infos;
+ size_t num_matching_proc_infos =
+ GetAllInfosMatchingName(name, matching_proc_infos);
+ if (num_matching_proc_infos == 1) {
+ return matching_proc_infos[0].kp_proc.p_pid;
+ }
+ return INVALID_NUB_PROCESS;
+}
+
+nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout,
+ char *err_str, size_t err_len) {
+ if (err_str && err_len > 0)
+ err_str[0] = '\0';
+ std::vector<struct kinfo_proc> matching_proc_infos;
+ size_t num_matching_proc_infos =
+ GetAllInfosMatchingName(name, matching_proc_infos);
+ if (num_matching_proc_infos == 0) {
+ DNBLogError("error: no processes match '%s'\n", name);
return INVALID_NUB_PROCESS;
-}
-
-nub_process_t
-DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
-{
- if (err_str && err_len > 0)
- err_str[0] = '\0';
- std::vector<struct kinfo_proc> matching_proc_infos;
- size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
- if (num_matching_proc_infos == 0)
- {
- DNBLogError ("error: no processes match '%s'\n", name);
- return INVALID_NUB_PROCESS;
- }
- else if (num_matching_proc_infos > 1)
- {
- DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name);
- size_t i;
- for (i=0; i<num_matching_proc_infos; ++i)
- DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
- return INVALID_NUB_PROCESS;
- }
-
- return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
-}
-
-nub_process_t
-DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len)
-{
- if (err_str && err_len > 0)
- err_str[0] = '\0';
-
- pid_t pid = INVALID_NUB_PROCESS;
- MachProcessSP processSP(new MachProcess);
- if (processSP.get())
- {
- DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid);
- pid = processSP->AttachForDebug (attach_pid, err_str, err_len);
-
- if (pid != INVALID_NUB_PROCESS)
- {
- bool res = AddProcessToMap(pid, processSP);
- UNUSED_IF_ASSERT_DISABLED(res);
- assert(res && "Couldn't add process to map!");
- spawn_waitpid_thread(pid);
- }
- }
-
- while (pid != INVALID_NUB_PROCESS)
- {
- // Wait for process to start up and hit entry point
- DNBLogThreadedIf (LOG_PROCESS,
- "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
- __FUNCTION__,
- pid);
- nub_event_t set_events = DNBProcessWaitForEvents (pid,
- eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
- true,
- timeout);
-
- DNBLogThreadedIf (LOG_PROCESS,
- "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
- __FUNCTION__,
- pid,
- set_events);
-
- if (set_events == 0)
- {
- if (err_str && err_len > 0)
- snprintf(err_str, err_len, "operation timed out");
- pid = INVALID_NUB_PROCESS;
- }
- else
- {
- if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
- {
- nub_state_t pid_state = DNBProcessGetState (pid);
- DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s",
- __FUNCTION__, pid, DNBStateAsString(pid_state));
-
- switch (pid_state)
- {
- case eStateInvalid:
- case eStateUnloaded:
- case eStateAttaching:
- case eStateLaunching:
- case eStateSuspended:
- break; // Ignore
-
- case eStateRunning:
- case eStateStepping:
- // Still waiting to stop at entry point...
- break;
-
- case eStateStopped:
- case eStateCrashed:
- return pid;
-
- case eStateDetached:
- case eStateExited:
- if (err_str && err_len > 0)
- snprintf(err_str, err_len, "process exited");
- return INVALID_NUB_PROCESS;
- }
- }
-
- DNBProcessResetEvents(pid, set_events);
- }
- }
-
+ } else if (num_matching_proc_infos > 1) {
+ DNBLogError("error: %llu processes match '%s':\n",
+ (uint64_t)num_matching_proc_infos, name);
+ size_t i;
+ for (i = 0; i < num_matching_proc_infos; ++i)
+ DNBLogError("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid,
+ matching_proc_infos[i].kp_proc.p_comm);
return INVALID_NUB_PROCESS;
-}
+ }
-size_t
-GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
-{
- size_t size = 0;
- int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
- u_int namelen = sizeof(name)/sizeof(int);
- int err;
-
- // Try to find out how many processes are around so we can
- // size the buffer appropriately. sysctl's man page specifically suggests
- // this approach, and says it returns a bit larger size than needed to
- // handle any new processes created between then and now.
-
- err = ::sysctl (name, namelen, NULL, &size, NULL, 0);
-
- if ((err < 0) && (err != ENOMEM))
- {
- proc_infos.clear();
- perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
- return 0;
- }
+ return DNBProcessAttach(matching_proc_infos[0].kp_proc.p_pid, timeout,
+ err_str, err_len);
+}
+nub_process_t DNBProcessAttach(nub_process_t attach_pid,
+ struct timespec *timeout, char *err_str,
+ size_t err_len) {
+ if (err_str && err_len > 0)
+ err_str[0] = '\0';
+
+ pid_t pid = INVALID_NUB_PROCESS;
+ MachProcessSP processSP(new MachProcess);
+ if (processSP.get()) {
+ DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...",
+ attach_pid);
+ pid = processSP->AttachForDebug(attach_pid, err_str, err_len);
+
+ if (pid != INVALID_NUB_PROCESS) {
+ bool res = AddProcessToMap(pid, processSP);
+ UNUSED_IF_ASSERT_DISABLED(res);
+ assert(res && "Couldn't add process to map!");
+ spawn_waitpid_thread(pid);
+ }
+ }
+
+ while (pid != INVALID_NUB_PROCESS) {
+ // Wait for process to start up and hit entry point
+ DNBLogThreadedIf(LOG_PROCESS, "%s DNBProcessWaitForEvent (%4.4x, "
+ "eEventProcessRunningStateChanged | "
+ "eEventProcessStoppedStateChanged, true, "
+ "INFINITE)...",
+ __FUNCTION__, pid);
+ nub_event_t set_events =
+ DNBProcessWaitForEvents(pid, eEventProcessRunningStateChanged |
+ eEventProcessStoppedStateChanged,
+ true, timeout);
+
+ DNBLogThreadedIf(LOG_PROCESS, "%s DNBProcessWaitForEvent (%4.4x, "
+ "eEventProcessRunningStateChanged | "
+ "eEventProcessStoppedStateChanged, true, "
+ "INFINITE) => 0x%8.8x",
+ __FUNCTION__, pid, set_events);
+
+ if (set_events == 0) {
+ if (err_str && err_len > 0)
+ snprintf(err_str, err_len, "operation timed out");
+ pid = INVALID_NUB_PROCESS;
+ } else {
+ if (set_events & (eEventProcessRunningStateChanged |
+ eEventProcessStoppedStateChanged)) {
+ nub_state_t pid_state = DNBProcessGetState(pid);
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "%s process %4.4x state changed (eEventProcessStateChanged): %s",
+ __FUNCTION__, pid, DNBStateAsString(pid_state));
+
+ switch (pid_state) {
+ case eStateInvalid:
+ case eStateUnloaded:
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateSuspended:
+ break; // Ignore
+
+ case eStateRunning:
+ case eStateStepping:
+ // Still waiting to stop at entry point...
+ break;
+
+ case eStateStopped:
+ case eStateCrashed:
+ return pid;
+
+ case eStateDetached:
+ case eStateExited:
+ if (err_str && err_len > 0)
+ snprintf(err_str, err_len, "process exited");
+ return INVALID_NUB_PROCESS;
+ }
+ }
+
+ DNBProcessResetEvents(pid, set_events);
+ }
+ }
+
+ return INVALID_NUB_PROCESS;
+}
+
+size_t GetAllInfos(std::vector<struct kinfo_proc> &proc_infos) {
+ size_t size = 0;
+ int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
+ u_int namelen = sizeof(name) / sizeof(int);
+ int err;
+
+ // Try to find out how many processes are around so we can
+ // size the buffer appropriately. sysctl's man page specifically suggests
+ // this approach, and says it returns a bit larger size than needed to
+ // handle any new processes created between then and now.
+
+ err = ::sysctl(name, namelen, NULL, &size, NULL, 0);
+
+ if ((err < 0) && (err != ENOMEM)) {
+ proc_infos.clear();
+ perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
+ return 0;
+ }
- // Increase the size of the buffer by a few processes in case more have
- // been spawned
- proc_infos.resize (size / sizeof(struct kinfo_proc));
- size = proc_infos.size() * sizeof(struct kinfo_proc); // Make sure we don't exceed our resize...
- err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0);
- if (err < 0)
- {
- proc_infos.clear();
- return 0;
- }
+ // Increase the size of the buffer by a few processes in case more have
+ // been spawned
+ proc_infos.resize(size / sizeof(struct kinfo_proc));
+ size = proc_infos.size() *
+ sizeof(struct kinfo_proc); // Make sure we don't exceed our resize...
+ err = ::sysctl(name, namelen, &proc_infos[0], &size, NULL, 0);
+ if (err < 0) {
+ proc_infos.clear();
+ return 0;
+ }
- // Trim down our array to fit what we actually got back
- proc_infos.resize(size / sizeof(struct kinfo_proc));
- return proc_infos.size();
+ // Trim down our array to fit what we actually got back
+ proc_infos.resize(size / sizeof(struct kinfo_proc));
+ return proc_infos.size();
}
static size_t
-GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos)
-{
+GetAllInfosMatchingName(const char *full_process_name,
+ std::vector<struct kinfo_proc> &matching_proc_infos) {
+
+ matching_proc_infos.clear();
+ if (full_process_name && full_process_name[0]) {
+ // We only get the process name, not the full path, from the proc_info. So
+ // just take the
+ // base name of the process name...
+ const char *process_name;
+ process_name = strrchr(full_process_name, '/');
+ if (process_name == NULL)
+ process_name = full_process_name;
+ else
+ process_name++;
- matching_proc_infos.clear();
- if (full_process_name && full_process_name[0])
- {
- // We only get the process name, not the full path, from the proc_info. So just take the
- // base name of the process name...
- const char *process_name;
- process_name = strrchr (full_process_name, '/');
- if (process_name == NULL)
- process_name = full_process_name;
- else
- process_name++;
-
- const size_t process_name_len = strlen(process_name);
- std::vector<struct kinfo_proc> proc_infos;
- const size_t num_proc_infos = GetAllInfos(proc_infos);
- if (num_proc_infos > 0)
- {
- uint32_t i;
- for (i=0; i<num_proc_infos; i++)
- {
- // Skip zombie processes and processes with unset status
- if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB)
- continue;
-
- // Check for process by name. We only check the first MAXCOMLEN
- // chars as that is all that kp_proc.p_comm holds.
-
- if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0)
- {
- if (process_name_len > MAXCOMLEN)
- {
- // We found a matching process name whose first MAXCOMLEN
- // characters match, but there is more to the name than
- // this. We need to get the full process name. Use proc_pidpath, which will get
- // us the full path to the executed process.
-
- char proc_path_buf[PATH_MAX];
-
- int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX);
- if (return_val > 0)
- {
- // Okay, now search backwards from that to see if there is a
- // slash in the name. Note, even though we got all the args we don't care
- // because the list data is just a bunch of concatenated null terminated strings
- // so strrchr will start from the end of argv0.
-
- const char *argv_basename = strrchr(proc_path_buf, '/');
- if (argv_basename)
- {
- // Skip the '/'
- ++argv_basename;
- }
- else
- {
- // We didn't find a directory delimiter in the process argv[0], just use what was in there
- argv_basename = proc_path_buf;
- }
-
- if (argv_basename)
- {
- if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0)
- {
- matching_proc_infos.push_back(proc_infos[i]);
- }
- }
- }
- }
- else
- {
- // We found a matching process, add it to our list
- matching_proc_infos.push_back(proc_infos[i]);
- }
+ const size_t process_name_len = strlen(process_name);
+ std::vector<struct kinfo_proc> proc_infos;
+ const size_t num_proc_infos = GetAllInfos(proc_infos);
+ if (num_proc_infos > 0) {
+ uint32_t i;
+ for (i = 0; i < num_proc_infos; i++) {
+ // Skip zombie processes and processes with unset status
+ if (proc_infos[i].kp_proc.p_stat == 0 ||
+ proc_infos[i].kp_proc.p_stat == SZOMB)
+ continue;
+
+ // Check for process by name. We only check the first MAXCOMLEN
+ // chars as that is all that kp_proc.p_comm holds.
+
+ if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm,
+ MAXCOMLEN) == 0) {
+ if (process_name_len > MAXCOMLEN) {
+ // We found a matching process name whose first MAXCOMLEN
+ // characters match, but there is more to the name than
+ // this. We need to get the full process name. Use proc_pidpath,
+ // which will get
+ // us the full path to the executed process.
+
+ char proc_path_buf[PATH_MAX];
+
+ int return_val = proc_pidpath(proc_infos[i].kp_proc.p_pid,
+ proc_path_buf, PATH_MAX);
+ if (return_val > 0) {
+ // Okay, now search backwards from that to see if there is a
+ // slash in the name. Note, even though we got all the args we
+ // don't care
+ // because the list data is just a bunch of concatenated null
+ // terminated strings
+ // so strrchr will start from the end of argv0.
+
+ const char *argv_basename = strrchr(proc_path_buf, '/');
+ if (argv_basename) {
+ // Skip the '/'
+ ++argv_basename;
+ } else {
+ // We didn't find a directory delimiter in the process argv[0],
+ // just use what was in there
+ argv_basename = proc_path_buf;
+ }
+
+ if (argv_basename) {
+ if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0) {
+ matching_proc_infos.push_back(proc_infos[i]);
}
+ }
}
+ } else {
+ // We found a matching process, add it to our list
+ matching_proc_infos.push_back(proc_infos[i]);
+ }
}
+ }
}
- // return the newly added matches.
- return matching_proc_infos.size();
+ }
+ // return the newly added matches.
+ return matching_proc_infos.size();
}
-nub_process_t
-DNBProcessAttachWait (const char *waitfor_process_name,
- nub_launch_flavor_t launch_flavor,
- bool ignore_existing,
- struct timespec *timeout_abstime,
- useconds_t waitfor_interval,
- char *err_str,
- size_t err_len,
- DNBShouldCancelCallback should_cancel_callback,
- void *callback_data)
-{
- DNBError prepare_error;
- std::vector<struct kinfo_proc> exclude_proc_infos;
- size_t num_exclude_proc_infos;
-
- // If the PrepareForAttach returns a valid token, use MachProcess to check
- // for the process, otherwise scan the process table.
-
- const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error);
-
- if (prepare_error.Fail())
- {
- DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString());
- return INVALID_NUB_PROCESS;
- }
+nub_process_t DNBProcessAttachWait(
+ const char *waitfor_process_name, nub_launch_flavor_t launch_flavor,
+ bool ignore_existing, struct timespec *timeout_abstime,
+ useconds_t waitfor_interval, char *err_str, size_t err_len,
+ DNBShouldCancelCallback should_cancel_callback, void *callback_data) {
+ DNBError prepare_error;
+ std::vector<struct kinfo_proc> exclude_proc_infos;
+ size_t num_exclude_proc_infos;
- if (attach_token == NULL)
- {
- if (ignore_existing)
- num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
- else
- num_exclude_proc_infos = 0;
- }
-
- DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
+ // If the PrepareForAttach returns a valid token, use MachProcess to check
+ // for the process, otherwise scan the process table.
- // Loop and try to find the process by name
- nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
+ const void *attach_token = MachProcess::PrepareForAttach(
+ waitfor_process_name, launch_flavor, true, prepare_error);
- while (waitfor_pid == INVALID_NUB_PROCESS)
- {
- if (attach_token != NULL)
- {
- nub_process_t pid;
- pid = MachProcess::CheckForProcess(attach_token, launch_flavor);
- if (pid != INVALID_NUB_PROCESS)
- {
- waitfor_pid = pid;
- break;
- }
- }
- else
- {
-
- // Get the current process list, and check for matches that
- // aren't in our original list. If anyone wants to attach
- // to an existing process by name, they should do it with
- // --attach=PROCNAME. Else we will wait for the first matching
- // process that wasn't in our exclusion list.
- std::vector<struct kinfo_proc> proc_infos;
- const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos);
- for (size_t i=0; i<num_proc_infos; i++)
- {
- nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
- for (size_t j=0; j<num_exclude_proc_infos; j++)
- {
- if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid)
- {
- // This process was in our exclusion list, don't use it.
- curr_pid = INVALID_NUB_PROCESS;
- break;
- }
- }
-
- // If we didn't find CURR_PID in our exclusion list, then use it.
- if (curr_pid != INVALID_NUB_PROCESS)
- {
- // We found our process!
- waitfor_pid = curr_pid;
- break;
- }
- }
- }
+ if (prepare_error.Fail()) {
+ DNBLogError("Error in PrepareForAttach: %s", prepare_error.AsString());
+ return INVALID_NUB_PROCESS;
+ }
- // If we haven't found our process yet, check for a timeout
- // and then sleep for a bit until we poll again.
- if (waitfor_pid == INVALID_NUB_PROCESS)
- {
- if (timeout_abstime != NULL)
- {
- // Check to see if we have a waitfor-duration option that
- // has timed out?
- if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime))
- {
- if (err_str && err_len > 0)
- snprintf(err_str, err_len, "operation timed out");
- DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name);
- return INVALID_NUB_PROCESS;
- }
- }
+ if (attach_token == NULL) {
+ if (ignore_existing)
+ num_exclude_proc_infos =
+ GetAllInfosMatchingName(waitfor_process_name, exclude_proc_infos);
+ else
+ num_exclude_proc_infos = 0;
+ }
- // Call the should cancel callback as well...
+ DNBLogThreadedIf(LOG_PROCESS, "Waiting for '%s' to appear...\n",
+ waitfor_process_name);
- if (should_cancel_callback != NULL
- && should_cancel_callback (callback_data))
- {
- DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback.");
- waitfor_pid = INVALID_NUB_PROCESS;
- break;
- }
+ // Loop and try to find the process by name
+ nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
- ::usleep (waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again
+ while (waitfor_pid == INVALID_NUB_PROCESS) {
+ if (attach_token != NULL) {
+ nub_process_t pid;
+ pid = MachProcess::CheckForProcess(attach_token, launch_flavor);
+ if (pid != INVALID_NUB_PROCESS) {
+ waitfor_pid = pid;
+ break;
+ }
+ } else {
+
+ // Get the current process list, and check for matches that
+ // aren't in our original list. If anyone wants to attach
+ // to an existing process by name, they should do it with
+ // --attach=PROCNAME. Else we will wait for the first matching
+ // process that wasn't in our exclusion list.
+ std::vector<struct kinfo_proc> proc_infos;
+ const size_t num_proc_infos =
+ GetAllInfosMatchingName(waitfor_process_name, proc_infos);
+ for (size_t i = 0; i < num_proc_infos; i++) {
+ nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
+ for (size_t j = 0; j < num_exclude_proc_infos; j++) {
+ if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid) {
+ // This process was in our exclusion list, don't use it.
+ curr_pid = INVALID_NUB_PROCESS;
+ break;
+ }
}
- }
- if (waitfor_pid != INVALID_NUB_PROCESS)
- {
- DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid);
- waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len);
- }
-
- bool success = waitfor_pid != INVALID_NUB_PROCESS;
- MachProcess::CleanupAfterAttach (attach_token, launch_flavor, success, prepare_error);
-
- return waitfor_pid;
-}
-
-nub_bool_t
-DNBProcessDetach (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- const bool remove = true;
- DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid);
- procSP->DisableAllBreakpoints(remove);
- procSP->DisableAllWatchpoints (remove);
- return procSP->Detach();
- }
- return false;
-}
-
-nub_bool_t
-DNBProcessKill (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->Kill ();
- }
- return false;
-}
-
-nub_bool_t
-DNBProcessSignal (nub_process_t pid, int signal)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->Signal (signal);
- }
- return false;
-}
-
-
-nub_bool_t
-DNBProcessInterrupt(nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->Interrupt();
- return false;
-}
-
-nub_bool_t
-DNBProcessSendEvent (nub_process_t pid, const char *event)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- // FIXME: Do something with the error...
- DNBError send_error;
- return procSP->SendEvent (event, send_error);
- }
- return false;
-}
-
-
-nub_bool_t
-DNBProcessIsAlive (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return MachTask::IsValid (procSP->Task().TaskPort());
- }
- return eStateInvalid;
+ // If we didn't find CURR_PID in our exclusion list, then use it.
+ if (curr_pid != INVALID_NUB_PROCESS) {
+ // We found our process!
+ waitfor_pid = curr_pid;
+ break;
+ }
+ }
+ }
+
+ // If we haven't found our process yet, check for a timeout
+ // and then sleep for a bit until we poll again.
+ if (waitfor_pid == INVALID_NUB_PROCESS) {
+ if (timeout_abstime != NULL) {
+ // Check to see if we have a waitfor-duration option that
+ // has timed out?
+ if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime)) {
+ if (err_str && err_len > 0)
+ snprintf(err_str, err_len, "operation timed out");
+ DNBLogError("error: waiting for process '%s' timed out.\n",
+ waitfor_process_name);
+ return INVALID_NUB_PROCESS;
+ }
+ }
+
+ // Call the should cancel callback as well...
+
+ if (should_cancel_callback != NULL &&
+ should_cancel_callback(callback_data)) {
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "DNBProcessAttachWait cancelled by should_cancel callback.");
+ waitfor_pid = INVALID_NUB_PROCESS;
+ break;
+ }
+
+ ::usleep(waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again
+ }
+ }
+
+ if (waitfor_pid != INVALID_NUB_PROCESS) {
+ DNBLogThreadedIf(LOG_PROCESS, "Attaching to %s with pid %i...\n",
+ waitfor_process_name, waitfor_pid);
+ waitfor_pid =
+ DNBProcessAttach(waitfor_pid, timeout_abstime, err_str, err_len);
+ }
+
+ bool success = waitfor_pid != INVALID_NUB_PROCESS;
+ MachProcess::CleanupAfterAttach(attach_token, launch_flavor, success,
+ prepare_error);
+
+ return waitfor_pid;
+}
+
+nub_bool_t DNBProcessDetach(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ const bool remove = true;
+ DNBLogThreaded(
+ "Disabling breakpoints and watchpoints, and detaching from %d.", pid);
+ procSP->DisableAllBreakpoints(remove);
+ procSP->DisableAllWatchpoints(remove);
+ return procSP->Detach();
+ }
+ return false;
+}
+
+nub_bool_t DNBProcessKill(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->Kill();
+ }
+ return false;
+}
+
+nub_bool_t DNBProcessSignal(nub_process_t pid, int signal) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->Signal(signal);
+ }
+ return false;
+}
+
+nub_bool_t DNBProcessInterrupt(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->Interrupt();
+ return false;
+}
+
+nub_bool_t DNBProcessSendEvent(nub_process_t pid, const char *event) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ // FIXME: Do something with the error...
+ DNBError send_error;
+ return procSP->SendEvent(event, send_error);
+ }
+ return false;
+}
+
+nub_bool_t DNBProcessIsAlive(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return MachTask::IsValid(procSP->Task().TaskPort());
+ }
+ return eStateInvalid;
}
//----------------------------------------------------------------------
// Process and Thread state information
//----------------------------------------------------------------------
-nub_state_t
-DNBProcessGetState (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetState();
- }
- return eStateInvalid;
+nub_state_t DNBProcessGetState(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetState();
+ }
+ return eStateInvalid;
}
//----------------------------------------------------------------------
// Process and Thread state information
//----------------------------------------------------------------------
-nub_bool_t
-DNBProcessGetExitStatus (nub_process_t pid, int* status)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetExitStatus(status);
- }
- return false;
-}
-
-nub_bool_t
-DNBProcessSetExitStatus (nub_process_t pid, int status)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- procSP->SetExitStatus(status);
- return true;
- }
- return false;
-}
-
-const char *
-DNBProcessGetExitInfo (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetExitInfo();
- }
- return NULL;
-}
-
-nub_bool_t
-DNBProcessSetExitInfo (nub_process_t pid, const char *info)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- procSP->SetExitInfo(info);
- return true;
- }
- return false;
-}
-
-const char *
-DNBThreadGetName (nub_process_t pid, nub_thread_t tid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->ThreadGetName(tid);
- return NULL;
-}
-
-
-nub_bool_t
-DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
- return false;
-}
-
-nub_state_t
-DNBThreadGetState (nub_process_t pid, nub_thread_t tid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->ThreadGetState(tid);
- }
- return eStateInvalid;
-}
-
-const char *
-DNBStateAsString(nub_state_t state)
-{
- switch (state)
- {
- case eStateInvalid: return "Invalid";
- case eStateUnloaded: return "Unloaded";
- case eStateAttaching: return "Attaching";
- case eStateLaunching: return "Launching";
- case eStateStopped: return "Stopped";
- case eStateRunning: return "Running";
- case eStateStepping: return "Stepping";
- case eStateCrashed: return "Crashed";
- case eStateDetached: return "Detached";
- case eStateExited: return "Exited";
- case eStateSuspended: return "Suspended";
- }
- return "nub_state_t ???";
-}
-
-Genealogy::ThreadActivitySP
-DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out)
-{
- Genealogy::ThreadActivitySP thread_activity_sp;
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- thread_activity_sp = procSP->GetGenealogyInfoForThread (tid, timed_out);
- return thread_activity_sp;
-}
-
-Genealogy::ProcessExecutableInfoSP
-DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx)
-{
- Genealogy::ProcessExecutableInfoSP image_info_sp;
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- image_info_sp = procSP->GetGenealogyImageInfo (idx);
- }
- return image_info_sp;
-}
-
-ThreadInfo::QoS
-DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetRequestedQoS (tid, tsd, dti_qos_class_index);
- }
- return ThreadInfo::QoS();
+nub_bool_t DNBProcessGetExitStatus(nub_process_t pid, int *status) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetExitStatus(status);
+ }
+ return false;
+}
+
+nub_bool_t DNBProcessSetExitStatus(nub_process_t pid, int status) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ procSP->SetExitStatus(status);
+ return true;
+ }
+ return false;
+}
+
+const char *DNBProcessGetExitInfo(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetExitInfo();
+ }
+ return NULL;
+}
+
+nub_bool_t DNBProcessSetExitInfo(nub_process_t pid, const char *info) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ procSP->SetExitInfo(info);
+ return true;
+ }
+ return false;
+}
+
+const char *DNBThreadGetName(nub_process_t pid, nub_thread_t tid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->ThreadGetName(tid);
+ return NULL;
+}
+
+nub_bool_t
+DNBThreadGetIdentifierInfo(nub_process_t pid, nub_thread_t tid,
+ thread_identifier_info_data_t *ident_info) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
+ return false;
+}
+
+nub_state_t DNBThreadGetState(nub_process_t pid, nub_thread_t tid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->ThreadGetState(tid);
+ }
+ return eStateInvalid;
+}
+
+const char *DNBStateAsString(nub_state_t state) {
+ switch (state) {
+ case eStateInvalid:
+ return "Invalid";
+ case eStateUnloaded:
+ return "Unloaded";
+ case eStateAttaching:
+ return "Attaching";
+ case eStateLaunching:
+ return "Launching";
+ case eStateStopped:
+ return "Stopped";
+ case eStateRunning:
+ return "Running";
+ case eStateStepping:
+ return "Stepping";
+ case eStateCrashed:
+ return "Crashed";
+ case eStateDetached:
+ return "Detached";
+ case eStateExited:
+ return "Exited";
+ case eStateSuspended:
+ return "Suspended";
+ }
+ return "nub_state_t ???";
+}
+
+Genealogy::ThreadActivitySP DNBGetGenealogyInfoForThread(nub_process_t pid,
+ nub_thread_t tid,
+ bool &timed_out) {
+ Genealogy::ThreadActivitySP thread_activity_sp;
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ thread_activity_sp = procSP->GetGenealogyInfoForThread(tid, timed_out);
+ return thread_activity_sp;
+}
+
+Genealogy::ProcessExecutableInfoSP DNBGetGenealogyImageInfo(nub_process_t pid,
+ size_t idx) {
+ Genealogy::ProcessExecutableInfoSP image_info_sp;
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ image_info_sp = procSP->GetGenealogyImageInfo(idx);
+ }
+ return image_info_sp;
+}
+
+ThreadInfo::QoS DNBGetRequestedQoSForThread(nub_process_t pid, nub_thread_t tid,
+ nub_addr_t tsd,
+ uint64_t dti_qos_class_index) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetRequestedQoS(tid, tsd, dti_qos_class_index);
+ }
+ return ThreadInfo::QoS();
+}
+
+nub_addr_t DNBGetPThreadT(nub_process_t pid, nub_thread_t tid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetPThreadT(tid);
+ }
+ return INVALID_NUB_ADDRESS;
+}
+
+nub_addr_t DNBGetDispatchQueueT(nub_process_t pid, nub_thread_t tid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetDispatchQueueT(tid);
+ }
+ return INVALID_NUB_ADDRESS;
}
nub_addr_t
-DNBGetPThreadT (nub_process_t pid, nub_thread_t tid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetPThreadT (tid);
- }
- return INVALID_NUB_ADDRESS;
+DNBGetTSDAddressForThread(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) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetTSDAddressForThread(
+ tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset,
+ plo_pthread_tsd_entry_size);
+ }
+ return INVALID_NUB_ADDRESS;
+}
+
+JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos(
+ nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetLoadedDynamicLibrariesInfos(pid, image_list_address,
+ image_count);
+ }
+ return JSONGenerator::ObjectSP();
+}
+
+JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetAllLoadedLibrariesInfos(pid);
+ }
+ return JSONGenerator::ObjectSP();
+}
+
+JSONGenerator::ObjectSP
+DNBGetLibrariesInfoForAddresses(nub_process_t pid,
+ std::vector<uint64_t> &macho_addresses) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetLibrariesInfoForAddresses(pid, macho_addresses);
+ }
+ return JSONGenerator::ObjectSP();
+}
+
+JSONGenerator::ObjectSP DNBGetSharedCacheInfo(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->GetSharedCacheInfo(pid);
+ }
+ return JSONGenerator::ObjectSP();
+}
+
+const char *DNBProcessGetExecutablePath(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->Path();
+ }
+ return NULL;
+}
+
+nub_size_t DNBProcessGetArgumentCount(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->ArgumentCount();
+ }
+ return 0;
+}
+
+const char *DNBProcessGetArgumentAtIndex(nub_process_t pid, nub_size_t idx) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->ArgumentAtIndex(idx);
+ }
+ return NULL;
}
-nub_addr_t
-DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetDispatchQueueT (tid);
- }
- return INVALID_NUB_ADDRESS;
-}
-
-nub_addr_t
-DNBGetTSDAddressForThread (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)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
- }
- return INVALID_NUB_ADDRESS;
-}
-
-JSONGenerator::ObjectSP
-DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count);
- }
- return JSONGenerator::ObjectSP();
-}
-
-JSONGenerator::ObjectSP
-DNBGetAllLoadedLibrariesInfos (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetAllLoadedLibrariesInfos (pid);
- }
- return JSONGenerator::ObjectSP();
-}
-
-JSONGenerator::ObjectSP
-DNBGetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetLibrariesInfoForAddresses (pid, macho_addresses);
- }
- return JSONGenerator::ObjectSP();
-}
-
-JSONGenerator::ObjectSP
-DNBGetSharedCacheInfo (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->GetSharedCacheInfo (pid);
- }
- return JSONGenerator::ObjectSP();
-}
-
-
-
-const char *
-DNBProcessGetExecutablePath (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->Path();
- }
- return NULL;
-}
-
-nub_size_t
-DNBProcessGetArgumentCount (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->ArgumentCount();
- }
- return 0;
-}
-
-const char *
-DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->ArgumentAtIndex (idx);
- }
- return NULL;
-}
-
-
//----------------------------------------------------------------------
// Execution control
//----------------------------------------------------------------------
-nub_bool_t
-DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions)
-{
- DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- DNBThreadResumeActions thread_actions (actions, num_actions);
-
- // Below we add a default thread plan just in case one wasn't
- // provided so all threads always know what they were supposed to do
- if (thread_actions.IsEmpty())
- {
- // No thread plans were given, so the default it to run all threads
- thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
- }
- else
- {
- // Some thread plans were given which means anything that wasn't
- // specified should remain stopped.
- thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
- }
- return procSP->Resume (thread_actions);
- }
- return false;
-}
-
-nub_bool_t
-DNBProcessHalt (nub_process_t pid)
-{
- DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->Signal (SIGSTOP);
- return false;
+nub_bool_t DNBProcessResume(nub_process_t pid,
+ const DNBThreadResumeAction *actions,
+ size_t num_actions) {
+ DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ DNBThreadResumeActions thread_actions(actions, num_actions);
+
+ // Below we add a default thread plan just in case one wasn't
+ // provided so all threads always know what they were supposed to do
+ if (thread_actions.IsEmpty()) {
+ // No thread plans were given, so the default it to run all threads
+ thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
+ } else {
+ // Some thread plans were given which means anything that wasn't
+ // specified should remain stopped.
+ thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
+ }
+ return procSP->Resume(thread_actions);
+ }
+ return false;
+}
+
+nub_bool_t DNBProcessHalt(nub_process_t pid) {
+ DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->Signal(SIGSTOP);
+ return false;
}
//
-//nub_bool_t
-//DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
+// nub_bool_t
+// DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
//{
-// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step);
+// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)",
+// __FUNCTION__, pid, tid, (uint32_t)step);
// MachProcessSP procSP;
// if (GetProcessSP (pid, procSP))
// {
@@ -1205,10 +1079,12 @@ DNBProcessHalt (nub_process_t pid)
// return false;
//}
//
-//nub_bool_t
-//DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal)
+// nub_bool_t
+// DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t
+// step, int signal)
//{
-// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
+// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u,
+// signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
// MachProcessSP procSP;
// if (GetProcessSP (pid, procSP))
// {
@@ -1217,80 +1093,68 @@ DNBProcessHalt (nub_process_t pid)
// return false;
//}
-nub_event_t
-DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout)
-{
- nub_event_t result = 0;
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- if (wait_for_set)
- result = procSP->Events().WaitForSetEvents(event_mask, timeout);
- else
- result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
- }
- return result;
+nub_event_t DNBProcessWaitForEvents(nub_process_t pid, nub_event_t event_mask,
+ bool wait_for_set,
+ struct timespec *timeout) {
+ nub_event_t result = 0;
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ if (wait_for_set)
+ result = procSP->Events().WaitForSetEvents(event_mask, timeout);
+ else
+ result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
+ }
+ return result;
}
-void
-DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- procSP->Events().ResetEvents(event_mask);
+void DNBProcessResetEvents(nub_process_t pid, nub_event_t event_mask) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ procSP->Events().ResetEvents(event_mask);
}
// Breakpoints
-nub_bool_t
-DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->CreateBreakpoint(addr, size, hardware) != NULL;
- return false;
+nub_bool_t DNBBreakpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size,
+ nub_bool_t hardware) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->CreateBreakpoint(addr, size, hardware) != NULL;
+ return false;
}
-nub_bool_t
-DNBBreakpointClear (nub_process_t pid, nub_addr_t addr)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->DisableBreakpoint(addr, true);
- return false; // Failed
+nub_bool_t DNBBreakpointClear(nub_process_t pid, nub_addr_t addr) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->DisableBreakpoint(addr, true);
+ return false; // Failed
}
-
//----------------------------------------------------------------------
// Watchpoints
//----------------------------------------------------------------------
-nub_bool_t
-DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL;
- return false;
+nub_bool_t DNBWatchpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size,
+ uint32_t watch_flags, nub_bool_t hardware) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL;
+ return false;
}
-nub_bool_t
-DNBWatchpointClear (nub_process_t pid, nub_addr_t addr)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->DisableWatchpoint(addr, true);
- return false; // Failed
+nub_bool_t DNBWatchpointClear(nub_process_t pid, nub_addr_t addr) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->DisableWatchpoint(addr, true);
+ return false; // Failed
}
//----------------------------------------------------------------------
// Return the number of supported hardware watchpoints.
//----------------------------------------------------------------------
-uint32_t
-DNBWatchpointGetNumSupportedHWP (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetNumSupportedHardwareWatchpoints();
- return 0;
+uint32_t DNBWatchpointGetNumSupportedHWP(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetNumSupportedHardwareWatchpoints();
+ return 0;
}
//----------------------------------------------------------------------
@@ -1300,95 +1164,89 @@ DNBWatchpointGetNumSupportedHWP (nub_pro
//
// RETURNS: number of bytes actually read
//----------------------------------------------------------------------
-nub_size_t
-DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->ReadMemory(addr, size, buf);
- return 0;
-}
-
-uint64_t
-DNBProcessMemoryReadInteger (nub_process_t pid, nub_addr_t addr, nub_size_t integer_size, uint64_t fail_value)
-{
- union Integers
- {
- uint8_t u8;
- uint16_t u16;
- uint32_t u32;
- uint64_t u64;
- };
-
- if (integer_size <= sizeof(uint64_t))
- {
- Integers ints;
- if (DNBProcessMemoryRead(pid, addr, integer_size, &ints) == integer_size)
- {
- switch (integer_size)
- {
- case 1: return ints.u8;
- case 2: return ints.u16;
- case 3: return ints.u32 & 0xffffffu;
- case 4: return ints.u32;
- case 5: return ints.u32 & 0x000000ffffffffffull;
- case 6: return ints.u32 & 0x0000ffffffffffffull;
- case 7: return ints.u32 & 0x00ffffffffffffffull;
- case 8: return ints.u64;
- }
- }
- }
- return fail_value;
-
-}
-
-nub_addr_t
-DNBProcessMemoryReadPointer (nub_process_t pid, nub_addr_t addr)
-{
- cpu_type_t cputype = DNBProcessGetCPUType (pid);
- if (cputype)
- {
- const nub_size_t pointer_size = (cputype & CPU_ARCH_ABI64) ? 8 : 4;
- return DNBProcessMemoryReadInteger(pid, addr, pointer_size, 0);
- }
- return 0;
-
-}
-
-std::string
-DNBProcessMemoryReadCString (nub_process_t pid, nub_addr_t addr)
-{
- std::string cstr;
- char buffer[256];
- const nub_size_t max_buffer_cstr_length = sizeof(buffer)-1;
- buffer[max_buffer_cstr_length] = '\0';
- nub_size_t length = 0;
- nub_addr_t curr_addr = addr;
- do
- {
- nub_size_t bytes_read = DNBProcessMemoryRead(pid, curr_addr, max_buffer_cstr_length, buffer);
- if (bytes_read == 0)
- break;
- length = strlen(buffer);
- cstr.append(buffer, length);
- curr_addr += length;
- } while (length == max_buffer_cstr_length);
- return cstr;
-}
-
-std::string
-DNBProcessMemoryReadCStringFixed (nub_process_t pid, nub_addr_t addr, nub_size_t fixed_length)
-{
- std::string cstr;
- char buffer[fixed_length+1];
- buffer[fixed_length] = '\0';
- nub_size_t bytes_read = DNBProcessMemoryRead(pid, addr, fixed_length, buffer);
- if (bytes_read > 0)
- cstr.assign(buffer);
- return cstr;
+nub_size_t DNBProcessMemoryRead(nub_process_t pid, nub_addr_t addr,
+ nub_size_t size, void *buf) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->ReadMemory(addr, size, buf);
+ return 0;
+}
+
+uint64_t DNBProcessMemoryReadInteger(nub_process_t pid, nub_addr_t addr,
+ nub_size_t integer_size,
+ uint64_t fail_value) {
+ union Integers {
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+ };
+
+ if (integer_size <= sizeof(uint64_t)) {
+ Integers ints;
+ if (DNBProcessMemoryRead(pid, addr, integer_size, &ints) == integer_size) {
+ switch (integer_size) {
+ case 1:
+ return ints.u8;
+ case 2:
+ return ints.u16;
+ case 3:
+ return ints.u32 & 0xffffffu;
+ case 4:
+ return ints.u32;
+ case 5:
+ return ints.u32 & 0x000000ffffffffffull;
+ case 6:
+ return ints.u32 & 0x0000ffffffffffffull;
+ case 7:
+ return ints.u32 & 0x00ffffffffffffffull;
+ case 8:
+ return ints.u64;
+ }
+ }
+ }
+ return fail_value;
+}
+
+nub_addr_t DNBProcessMemoryReadPointer(nub_process_t pid, nub_addr_t addr) {
+ cpu_type_t cputype = DNBProcessGetCPUType(pid);
+ if (cputype) {
+ const nub_size_t pointer_size = (cputype & CPU_ARCH_ABI64) ? 8 : 4;
+ return DNBProcessMemoryReadInteger(pid, addr, pointer_size, 0);
+ }
+ return 0;
+}
+
+std::string DNBProcessMemoryReadCString(nub_process_t pid, nub_addr_t addr) {
+ std::string cstr;
+ char buffer[256];
+ const nub_size_t max_buffer_cstr_length = sizeof(buffer) - 1;
+ buffer[max_buffer_cstr_length] = '\0';
+ nub_size_t length = 0;
+ nub_addr_t curr_addr = addr;
+ do {
+ nub_size_t bytes_read =
+ DNBProcessMemoryRead(pid, curr_addr, max_buffer_cstr_length, buffer);
+ if (bytes_read == 0)
+ break;
+ length = strlen(buffer);
+ cstr.append(buffer, length);
+ curr_addr += length;
+ } while (length == max_buffer_cstr_length);
+ return cstr;
+}
+
+std::string DNBProcessMemoryReadCStringFixed(nub_process_t pid, nub_addr_t addr,
+ nub_size_t fixed_length) {
+ std::string cstr;
+ char buffer[fixed_length + 1];
+ buffer[fixed_length] = '\0';
+ nub_size_t bytes_read = DNBProcessMemoryRead(pid, addr, fixed_length, buffer);
+ if (bytes_read > 0)
+ cstr.assign(buffer);
+ return cstr;
}
-
//----------------------------------------------------------------------
// Write memory to the address space of process PID. This call will take
// care of setting and restoring permissions and breaking up the memory
@@ -1396,31 +1254,27 @@ DNBProcessMemoryReadCStringFixed (nub_pr
//
// RETURNS: number of bytes actually written
//----------------------------------------------------------------------
-nub_size_t
-DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->WriteMemory(addr, size, buf);
- return 0;
-}
-
-nub_addr_t
-DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->Task().AllocateMemory (size, permissions);
- return 0;
-}
-
-nub_bool_t
-DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->Task().DeallocateMemory (addr);
- return 0;
+nub_size_t DNBProcessMemoryWrite(nub_process_t pid, nub_addr_t addr,
+ nub_size_t size, const void *buf) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->WriteMemory(addr, size, buf);
+ return 0;
+}
+
+nub_addr_t DNBProcessMemoryAllocate(nub_process_t pid, nub_size_t size,
+ uint32_t permissions) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->Task().AllocateMemory(size, permissions);
+ return 0;
+}
+
+nub_bool_t DNBProcessMemoryDeallocate(nub_process_t pid, nub_addr_t addr) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->Task().DeallocateMemory(addr);
+ return 0;
}
//----------------------------------------------------------------------
@@ -1437,99 +1291,87 @@ DNBProcessMemoryDeallocate (nub_process_
// or if we do not yet have a valid launched process.
//
//----------------------------------------------------------------------
-int
-DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->Task().GetMemoryRegionInfo (addr, region_info);
+int DNBProcessMemoryRegionInfo(nub_process_t pid, nub_addr_t addr,
+ DNBRegionInfo *region_info) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->Task().GetMemoryRegionInfo(addr, region_info);
+
+ return -1;
+}
+
+std::string DNBProcessGetProfileData(nub_process_t pid,
+ DNBProfileDataScanType scanType) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->Task().GetProfileData(scanType);
+
+ return std::string("");
+}
+
+nub_bool_t DNBProcessSetEnableAsyncProfiling(nub_process_t pid,
+ nub_bool_t enable,
+ uint64_t interval_usec,
+ DNBProfileDataScanType scan_type) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type);
+ return true;
+ }
- return -1;
-}
-
-std::string
-DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->Task().GetProfileData(scanType);
-
- return std::string("");
-}
-
-nub_bool_t
-DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type);
- return true;
- }
-
- return false;
+ return false;
}
//----------------------------------------------------------------------
// Get the number of threads for the specified process.
//----------------------------------------------------------------------
-nub_size_t
-DNBProcessGetNumThreads (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetNumThreads();
- return 0;
+nub_size_t DNBProcessGetNumThreads(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetNumThreads();
+ return 0;
}
//----------------------------------------------------------------------
// Get the thread ID of the current thread.
//----------------------------------------------------------------------
-nub_thread_t
-DNBProcessGetCurrentThread (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetCurrentThread();
- return 0;
+nub_thread_t DNBProcessGetCurrentThread(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetCurrentThread();
+ return 0;
}
//----------------------------------------------------------------------
// Get the mach port number of the current thread.
//----------------------------------------------------------------------
-nub_thread_t
-DNBProcessGetCurrentThreadMachPort (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetCurrentThreadMachPort();
- return 0;
+nub_thread_t DNBProcessGetCurrentThreadMachPort(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetCurrentThreadMachPort();
+ return 0;
}
//----------------------------------------------------------------------
// Change the current thread.
//----------------------------------------------------------------------
-nub_thread_t
-DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->SetCurrentThread (tid);
- return INVALID_NUB_THREAD;
+nub_thread_t DNBProcessSetCurrentThread(nub_process_t pid, nub_thread_t tid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->SetCurrentThread(tid);
+ return INVALID_NUB_THREAD;
}
-
//----------------------------------------------------------------------
// Dump a string describing a thread's stop reason to the specified file
// handle
//----------------------------------------------------------------------
-nub_bool_t
-DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetThreadStoppedReason (tid, stop_info);
- return false;
+nub_bool_t DNBThreadGetStopReason(nub_process_t pid, nub_thread_t tid,
+ struct DNBThreadStopInfo *stop_info) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetThreadStoppedReason(tid, stop_info);
+ return false;
}
//----------------------------------------------------------------------
@@ -1539,61 +1381,49 @@ DNBThreadGetStopReason (nub_process_t pi
// string from a static buffer that must be copied prior to subsequent
// calls.
//----------------------------------------------------------------------
-const char *
-DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetThreadInfo (tid);
- return NULL;
+const char *DNBThreadGetInfo(nub_process_t pid, nub_thread_t tid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetThreadInfo(tid);
+ return NULL;
}
//----------------------------------------------------------------------
// Get the thread ID given a thread index.
//----------------------------------------------------------------------
-nub_thread_t
-DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetThreadAtIndex (thread_idx);
- return INVALID_NUB_THREAD;
+nub_thread_t DNBProcessGetThreadAtIndex(nub_process_t pid, size_t thread_idx) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetThreadAtIndex(thread_idx);
+ return INVALID_NUB_THREAD;
}
//----------------------------------------------------------------------
-// Do whatever is needed to sync the thread's register state with it's kernel values.
-//----------------------------------------------------------------------
-nub_bool_t
-DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->SyncThreadState (tid);
- return false;
-
-}
-
-nub_addr_t
-DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid)
-{
- MachProcessSP procSP;
- DNBError err;
- if (GetProcessSP (pid, procSP))
- return procSP->Task().GetDYLDAllImageInfosAddress (err);
- return INVALID_NUB_ADDRESS;
-}
-
-
-nub_bool_t
-DNBProcessSharedLibrariesUpdated(nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- procSP->SharedLibrariesUpdated ();
- return true;
- }
- return false;
+// Do whatever is needed to sync the thread's register state with it's kernel
+// values.
+//----------------------------------------------------------------------
+nub_bool_t DNBProcessSyncThreadState(nub_process_t pid, nub_thread_t tid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->SyncThreadState(tid);
+ return false;
+}
+
+nub_addr_t DNBProcessGetSharedLibraryInfoAddress(nub_process_t pid) {
+ MachProcessSP procSP;
+ DNBError err;
+ if (GetProcessSP(pid, procSP))
+ return procSP->Task().GetDYLDAllImageInfosAddress(err);
+ return INVALID_NUB_ADDRESS;
+}
+
+nub_bool_t DNBProcessSharedLibrariesUpdated(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ procSP->SharedLibrariesUpdated();
+ return true;
+ }
+ return false;
}
//----------------------------------------------------------------------
@@ -1602,409 +1432,334 @@ DNBProcessSharedLibrariesUpdated(nub_pro
// state changed event if only_changed is non-zero.
//----------------------------------------------------------------------
nub_size_t
-DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->CopyImageInfos (image_infos, only_changed);
-
- // If we have no process, then return NULL for the shared library info
- // and zero for shared library count
- *image_infos = NULL;
- return 0;
+DNBProcessGetSharedLibraryInfo(nub_process_t pid, nub_bool_t only_changed,
+ struct DNBExecutableImageInfo **image_infos) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->CopyImageInfos(image_infos, only_changed);
+
+ // If we have no process, then return NULL for the shared library info
+ // and zero for shared library count
+ *image_infos = NULL;
+ return 0;
}
-uint32_t
-DNBGetRegisterCPUType()
-{
- return DNBArchProtocol::GetRegisterCPUType ();
-
+uint32_t DNBGetRegisterCPUType() {
+ return DNBArchProtocol::GetRegisterCPUType();
}
//----------------------------------------------------------------------
// Get the register set information for a specific thread.
//----------------------------------------------------------------------
-const DNBRegisterSetInfo *
-DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
-{
- return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
+const DNBRegisterSetInfo *DNBGetRegisterSetInfo(nub_size_t *num_reg_sets) {
+ return DNBArchProtocol::GetRegisterSetInfo(num_reg_sets);
}
-
//----------------------------------------------------------------------
// Read a register value by register set and register index.
//----------------------------------------------------------------------
-nub_bool_t
-DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value)
-{
- MachProcessSP procSP;
- ::bzero (value, sizeof(DNBRegisterValue));
- if (GetProcessSP (pid, procSP))
- {
- if (tid != INVALID_NUB_THREAD)
- return procSP->GetRegisterValue (tid, set, reg, value);
- }
- return false;
-}
-
-nub_bool_t
-DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value)
-{
+nub_bool_t DNBThreadGetRegisterValueByID(nub_process_t pid, nub_thread_t tid,
+ uint32_t set, uint32_t reg,
+ DNBRegisterValue *value) {
+ MachProcessSP procSP;
+ ::bzero(value, sizeof(DNBRegisterValue));
+ if (GetProcessSP(pid, procSP)) {
if (tid != INVALID_NUB_THREAD)
- {
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->SetRegisterValue (tid, set, reg, value);
- }
- return false;
-}
-
-nub_size_t
-DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- if (tid != INVALID_NUB_THREAD)
- return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len);
- }
- ::bzero (buf, buf_len);
- return 0;
-
-}
-
-nub_size_t
-DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- if (tid != INVALID_NUB_THREAD)
- return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len);
- }
- return 0;
-}
-
-uint32_t
-DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid)
-{
+ return procSP->GetRegisterValue(tid, set, reg, value);
+ }
+ return false;
+}
+
+nub_bool_t DNBThreadSetRegisterValueByID(nub_process_t pid, nub_thread_t tid,
+ uint32_t set, uint32_t reg,
+ const DNBRegisterValue *value) {
+ if (tid != INVALID_NUB_THREAD) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->SetRegisterValue(tid, set, reg, value);
+ }
+ return false;
+}
+
+nub_size_t DNBThreadGetRegisterContext(nub_process_t pid, nub_thread_t tid,
+ void *buf, size_t buf_len) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
if (tid != INVALID_NUB_THREAD)
- {
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetThreadList().SaveRegisterState (tid);
- }
- return 0;
+ return procSP->GetThreadList().GetRegisterContext(tid, buf, buf_len);
+ }
+ ::bzero(buf, buf_len);
+ return 0;
}
-nub_bool_t
-DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id)
-{
+
+nub_size_t DNBThreadSetRegisterContext(nub_process_t pid, nub_thread_t tid,
+ const void *buf, size_t buf_len) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
if (tid != INVALID_NUB_THREAD)
- {
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetThreadList().RestoreRegisterState (tid, save_id);
- }
- return false;
+ return procSP->GetThreadList().SetRegisterContext(tid, buf, buf_len);
+ }
+ return 0;
+}
+
+uint32_t DNBThreadSaveRegisterState(nub_process_t pid, nub_thread_t tid) {
+ if (tid != INVALID_NUB_THREAD) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetThreadList().SaveRegisterState(tid);
+ }
+ return 0;
+}
+nub_bool_t DNBThreadRestoreRegisterState(nub_process_t pid, nub_thread_t tid,
+ uint32_t save_id) {
+ if (tid != INVALID_NUB_THREAD) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetThreadList().RestoreRegisterState(tid, save_id);
+ }
+ return false;
}
-
-
//----------------------------------------------------------------------
// Read a register value by name.
//----------------------------------------------------------------------
-nub_bool_t
-DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value)
-{
- MachProcessSP procSP;
- ::bzero (value, sizeof(DNBRegisterValue));
- if (GetProcessSP (pid, procSP))
- {
- const struct DNBRegisterSetInfo *set_info;
- nub_size_t num_reg_sets = 0;
- set_info = DNBGetRegisterSetInfo (&num_reg_sets);
- if (set_info)
- {
- uint32_t set = reg_set;
- uint32_t reg;
- if (set == REGISTER_SET_ALL)
- {
- for (set = 1; set < num_reg_sets; ++set)
- {
- for (reg = 0; reg < set_info[set].num_registers; ++reg)
- {
- if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
- return procSP->GetRegisterValue (tid, set, reg, value);
- }
- }
- }
- else
- {
- for (reg = 0; reg < set_info[set].num_registers; ++reg)
- {
- if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
- return procSP->GetRegisterValue (tid, set, reg, value);
- }
- }
+nub_bool_t DNBThreadGetRegisterValueByName(nub_process_t pid, nub_thread_t tid,
+ uint32_t reg_set,
+ const char *reg_name,
+ DNBRegisterValue *value) {
+ MachProcessSP procSP;
+ ::bzero(value, sizeof(DNBRegisterValue));
+ if (GetProcessSP(pid, procSP)) {
+ const struct DNBRegisterSetInfo *set_info;
+ nub_size_t num_reg_sets = 0;
+ set_info = DNBGetRegisterSetInfo(&num_reg_sets);
+ if (set_info) {
+ uint32_t set = reg_set;
+ uint32_t reg;
+ if (set == REGISTER_SET_ALL) {
+ for (set = 1; set < num_reg_sets; ++set) {
+ for (reg = 0; reg < set_info[set].num_registers; ++reg) {
+ if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
+ return procSP->GetRegisterValue(tid, set, reg, value);
+ }
+ }
+ } else {
+ for (reg = 0; reg < set_info[set].num_registers; ++reg) {
+ if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
+ return procSP->GetRegisterValue(tid, set, reg, value);
}
+ }
}
- return false;
+ }
+ return false;
}
-
//----------------------------------------------------------------------
// Read a register set and register number from the register name.
//----------------------------------------------------------------------
-nub_bool_t
-DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info)
-{
- const struct DNBRegisterSetInfo *set_info;
- nub_size_t num_reg_sets = 0;
- set_info = DNBGetRegisterSetInfo (&num_reg_sets);
- if (set_info)
- {
- uint32_t set, reg;
- for (set = 1; set < num_reg_sets; ++set)
- {
- for (reg = 0; reg < set_info[set].num_registers; ++reg)
- {
- if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
- {
- *info = set_info[set].registers[reg];
- return true;
- }
- }
- }
-
- for (set = 1; set < num_reg_sets; ++set)
- {
- uint32_t reg;
- for (reg = 0; reg < set_info[set].num_registers; ++reg)
- {
- if (set_info[set].registers[reg].alt == NULL)
- continue;
-
- if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0)
- {
- *info = set_info[set].registers[reg];
- return true;
- }
- }
+nub_bool_t DNBGetRegisterInfoByName(const char *reg_name,
+ DNBRegisterInfo *info) {
+ const struct DNBRegisterSetInfo *set_info;
+ nub_size_t num_reg_sets = 0;
+ set_info = DNBGetRegisterSetInfo(&num_reg_sets);
+ if (set_info) {
+ uint32_t set, reg;
+ for (set = 1; set < num_reg_sets; ++set) {
+ for (reg = 0; reg < set_info[set].num_registers; ++reg) {
+ if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) {
+ *info = set_info[set].registers[reg];
+ return true;
+ }
+ }
+ }
+
+ for (set = 1; set < num_reg_sets; ++set) {
+ uint32_t reg;
+ for (reg = 0; reg < set_info[set].num_registers; ++reg) {
+ if (set_info[set].registers[reg].alt == NULL)
+ continue;
+
+ if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0) {
+ *info = set_info[set].registers[reg];
+ return true;
}
+ }
}
+ }
- ::bzero (info, sizeof(DNBRegisterInfo));
- return false;
+ ::bzero(info, sizeof(DNBRegisterInfo));
+ return false;
}
-
//----------------------------------------------------------------------
// Set the name to address callback function that this nub can use
// for any name to address lookups that are needed.
//----------------------------------------------------------------------
-nub_bool_t
-DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- procSP->SetNameToAddressCallback (callback, baton);
- return true;
- }
- return false;
+nub_bool_t DNBProcessSetNameToAddressCallback(nub_process_t pid,
+ DNBCallbackNameToAddress callback,
+ void *baton) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ procSP->SetNameToAddressCallback(callback, baton);
+ return true;
+ }
+ return false;
}
-
//----------------------------------------------------------------------
// Set the name to address callback function that this nub can use
// for any name to address lookups that are needed.
//----------------------------------------------------------------------
-nub_bool_t
-DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- procSP->SetSharedLibraryInfoCallback (callback, baton);
- return true;
- }
- return false;
-}
-
-nub_addr_t
-DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- {
- return procSP->LookupSymbol (name, shlib);
- }
- return INVALID_NUB_ADDRESS;
-}
-
-
-nub_size_t
-DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetAvailableSTDOUT (buf, buf_size);
- return 0;
-}
-
-nub_size_t
-DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetAvailableSTDERR (buf, buf_size);
- return 0;
-}
-
-nub_size_t
-DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetAsyncProfileData (buf, buf_size);
- return 0;
-}
-
-DarwinLogEventVector
-DNBProcessGetAvailableDarwinLogEvents(nub_process_t pid)
-{
- return DarwinLogCollector::GetEventsForProcess(pid);
-}
-
-nub_size_t
-DNBProcessGetStopCount (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->StopCount();
- return 0;
-}
-
-uint32_t
-DNBProcessGetCPUType (nub_process_t pid)
-{
- MachProcessSP procSP;
- if (GetProcessSP (pid, procSP))
- return procSP->GetCPUType ();
- return 0;
-
-}
-
-nub_bool_t
-DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
-{
- if (path == NULL || path[0] == '\0')
- return false;
-
- char max_path[PATH_MAX];
- std::string result;
- CFString::GlobPath(path, result);
-
- if (result.empty())
- result = path;
-
- struct stat path_stat;
- if (::stat(path, &path_stat) == 0)
- {
- if ((path_stat.st_mode & S_IFMT) == S_IFDIR)
- {
- CFBundle bundle (path);
- CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
- if (url.get())
- {
- if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size))
- return true;
- }
- }
- }
-
- if (realpath(path, max_path))
- {
- // Found the path relatively...
- ::strncpy(resolved_path, max_path, resolved_path_size);
- return strlen(resolved_path) + 1 < resolved_path_size;
- }
- else
- {
- // Not a relative path, check the PATH environment variable if the
- const char *PATH = getenv("PATH");
- if (PATH)
- {
- const char *curr_path_start = PATH;
- const char *curr_path_end;
- while (curr_path_start && *curr_path_start)
- {
- curr_path_end = strchr(curr_path_start, ':');
- if (curr_path_end == NULL)
- {
- result.assign(curr_path_start);
- curr_path_start = NULL;
- }
- else if (curr_path_end > curr_path_start)
- {
- size_t len = curr_path_end - curr_path_start;
- result.assign(curr_path_start, len);
- curr_path_start += len + 1;
- }
- else
- break;
-
- result += '/';
- result += path;
- struct stat s;
- if (stat(result.c_str(), &s) == 0)
- {
- ::strncpy(resolved_path, result.c_str(), resolved_path_size);
- return result.size() + 1 < resolved_path_size;
- }
- }
- }
- }
- return false;
-}
-
-bool
-DNBGetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch)
-{
- return MachProcess::GetOSVersionNumbers (major, minor, patch);
-}
-
-
-void
-DNBInitialize()
-{
- DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
-#if defined (__i386__) || defined (__x86_64__)
- DNBArchImplI386::Initialize();
- DNBArchImplX86_64::Initialize();
-#elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
- DNBArchMachARM::Initialize();
- DNBArchMachARM64::Initialize();
+nub_bool_t DNBProcessSetSharedLibraryInfoCallback(
+ nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback,
+ void *baton) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ procSP->SetSharedLibraryInfoCallback(callback, baton);
+ return true;
+ }
+ return false;
+}
+
+nub_addr_t DNBProcessLookupAddress(nub_process_t pid, const char *name,
+ const char *shlib) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP)) {
+ return procSP->LookupSymbol(name, shlib);
+ }
+ return INVALID_NUB_ADDRESS;
+}
+
+nub_size_t DNBProcessGetAvailableSTDOUT(nub_process_t pid, char *buf,
+ nub_size_t buf_size) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetAvailableSTDOUT(buf, buf_size);
+ return 0;
+}
+
+nub_size_t DNBProcessGetAvailableSTDERR(nub_process_t pid, char *buf,
+ nub_size_t buf_size) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetAvailableSTDERR(buf, buf_size);
+ return 0;
+}
+
+nub_size_t DNBProcessGetAvailableProfileData(nub_process_t pid, char *buf,
+ nub_size_t buf_size) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetAsyncProfileData(buf, buf_size);
+ return 0;
+}
+
+DarwinLogEventVector DNBProcessGetAvailableDarwinLogEvents(nub_process_t pid) {
+ return DarwinLogCollector::GetEventsForProcess(pid);
+}
+
+nub_size_t DNBProcessGetStopCount(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->StopCount();
+ return 0;
+}
+
+uint32_t DNBProcessGetCPUType(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetCPUType();
+ return 0;
+}
+
+nub_bool_t DNBResolveExecutablePath(const char *path, char *resolved_path,
+ size_t resolved_path_size) {
+ if (path == NULL || path[0] == '\0')
+ return false;
+
+ char max_path[PATH_MAX];
+ std::string result;
+ CFString::GlobPath(path, result);
+
+ if (result.empty())
+ result = path;
+
+ struct stat path_stat;
+ if (::stat(path, &path_stat) == 0) {
+ if ((path_stat.st_mode & S_IFMT) == S_IFDIR) {
+ CFBundle bundle(path);
+ CFReleaser<CFURLRef> url(bundle.CopyExecutableURL());
+ if (url.get()) {
+ if (::CFURLGetFileSystemRepresentation(
+ url.get(), true, (UInt8 *)resolved_path, resolved_path_size))
+ return true;
+ }
+ }
+ }
+
+ if (realpath(path, max_path)) {
+ // Found the path relatively...
+ ::strncpy(resolved_path, max_path, resolved_path_size);
+ return strlen(resolved_path) + 1 < resolved_path_size;
+ } else {
+ // Not a relative path, check the PATH environment variable if the
+ const char *PATH = getenv("PATH");
+ if (PATH) {
+ const char *curr_path_start = PATH;
+ const char *curr_path_end;
+ while (curr_path_start && *curr_path_start) {
+ curr_path_end = strchr(curr_path_start, ':');
+ if (curr_path_end == NULL) {
+ result.assign(curr_path_start);
+ curr_path_start = NULL;
+ } else if (curr_path_end > curr_path_start) {
+ size_t len = curr_path_end - curr_path_start;
+ result.assign(curr_path_start, len);
+ curr_path_start += len + 1;
+ } else
+ break;
+
+ result += '/';
+ result += path;
+ struct stat s;
+ if (stat(result.c_str(), &s) == 0) {
+ ::strncpy(resolved_path, result.c_str(), resolved_path_size);
+ return result.size() + 1 < resolved_path_size;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool DNBGetOSVersionNumbers(uint64_t *major, uint64_t *minor, uint64_t *patch) {
+ return MachProcess::GetOSVersionNumbers(major, minor, patch);
+}
+
+void DNBInitialize() {
+ DNBLogThreadedIf(LOG_PROCESS, "DNBInitialize ()");
+#if defined(__i386__) || defined(__x86_64__)
+ DNBArchImplI386::Initialize();
+ DNBArchImplX86_64::Initialize();
+#elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+ DNBArchMachARM::Initialize();
+ DNBArchMachARM64::Initialize();
#endif
}
-void
-DNBTerminate()
-{
-}
+void DNBTerminate() {}
-nub_bool_t
-DNBSetArchitecture (const char *arch)
-{
- if (arch && arch[0])
- {
- if (strcasecmp (arch, "i386") == 0)
- return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386);
- else if ((strcasecmp (arch, "x86_64") == 0) || (strcasecmp (arch, "x86_64h") == 0))
- return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64);
- else if (strstr (arch, "arm64") == arch || strstr (arch, "armv8") == arch || strstr (arch, "aarch64") == arch)
- return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM64);
- else if (strstr (arch, "arm") == arch)
- return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM);
- }
- return false;
+nub_bool_t DNBSetArchitecture(const char *arch) {
+ if (arch && arch[0]) {
+ if (strcasecmp(arch, "i386") == 0)
+ return DNBArchProtocol::SetArchitecture(CPU_TYPE_I386);
+ else if ((strcasecmp(arch, "x86_64") == 0) ||
+ (strcasecmp(arch, "x86_64h") == 0))
+ return DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64);
+ else if (strstr(arch, "arm64") == arch || strstr(arch, "armv8") == arch ||
+ strstr(arch, "aarch64") == arch)
+ return DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64);
+ else if (strstr(arch, "arm") == arch)
+ return DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM);
+ }
+ return false;
}
Modified: lldb/trunk/tools/debugserver/source/DNB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNB.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNB.h (original)
+++ lldb/trunk/tools/debugserver/source/DNB.h Tue Sep 6 15:57:50 2016
@@ -14,48 +14,49 @@
#ifndef __DNB_h__
#define __DNB_h__
+#include "DNBDefs.h"
+#include "JSONGenerator.h"
#include "MacOSX/DarwinLog/DarwinLogEvent.h"
#include "MacOSX/Genealogy.h"
#include "MacOSX/ThreadInfo.h"
-#include "JSONGenerator.h"
-#include "DNBDefs.h"
#include <mach/thread_info.h>
#include <string>
#define DNB_EXPORT __attribute__((visibility("default")))
#ifndef CPU_TYPE_ARM64
-#define CPU_TYPE_ARM64 ((cpu_type_t) 12 | 0x01000000)
+#define CPU_TYPE_ARM64 ((cpu_type_t)12 | 0x01000000)
#endif
-typedef bool (*DNBShouldCancelCallback) (void *);
+typedef bool (*DNBShouldCancelCallback)(void *);
-void DNBInitialize ();
-void DNBTerminate ();
+void DNBInitialize();
+void DNBTerminate();
-nub_bool_t DNBSetArchitecture (const char *arch);
+nub_bool_t DNBSetArchitecture(const char *arch);
//----------------------------------------------------------------------
// Process control
//----------------------------------------------------------------------
-nub_process_t DNBProcessLaunch (const char *path,
- char const *argv[],
- const char *envp[],
- const char *working_directory, // NULL => don't change, non-NULL => set working directory for inferior to this
- const char *stdin_path,
- const char *stdout_path,
- const char *stderr_path,
- bool no_stdio,
- nub_launch_flavor_t launch_flavor,
- int disable_aslr,
- const char *event_data,
- char *err_str,
- size_t err_len);
-
-nub_process_t DNBProcessGetPIDByName (const char *name);
-nub_process_t DNBProcessAttach (nub_process_t pid, struct timespec *timeout, char *err_str, size_t err_len);
-nub_process_t DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len);
-nub_process_t DNBProcessAttachWait (const char *wait_name, nub_launch_flavor_t launch_flavor, bool ignore_existing, struct timespec *timeout, useconds_t interval, char *err_str, size_t err_len, DNBShouldCancelCallback should_cancel = NULL, void *callback_data = NULL);
+nub_process_t DNBProcessLaunch(
+ const char *path, char const *argv[], const char *envp[],
+ const char *working_directory, // NULL => don't change, non-NULL => set
+ // working directory for inferior to this
+ const char *stdin_path, const char *stdout_path, const char *stderr_path,
+ bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr,
+ const char *event_data, char *err_str, size_t err_len);
+
+nub_process_t DNBProcessGetPIDByName(const char *name);
+nub_process_t DNBProcessAttach(nub_process_t pid, struct timespec *timeout,
+ char *err_str, size_t err_len);
+nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout,
+ char *err_str, size_t err_len);
+nub_process_t
+DNBProcessAttachWait(const char *wait_name, nub_launch_flavor_t launch_flavor,
+ bool ignore_existing, struct timespec *timeout,
+ useconds_t interval, char *err_str, size_t err_len,
+ DNBShouldCancelCallback should_cancel = NULL,
+ void *callback_data = NULL);
// Resume a process with exact instructions on what to do with each thread:
// - If no thread actions are supplied (actions is NULL or num_actions is zero),
// then all threads are continued.
@@ -64,117 +65,177 @@ nub_process_t DNBProcessAttachWait
// explicit thread action can be made by making a thread action with a tid of
// INVALID_NUB_THREAD. If there is no default action, those threads will
// remain stopped.
-nub_bool_t DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions) DNB_EXPORT;
-nub_bool_t DNBProcessHalt (nub_process_t pid) DNB_EXPORT;
-nub_bool_t DNBProcessDetach (nub_process_t pid) DNB_EXPORT;
-nub_bool_t DNBProcessSignal (nub_process_t pid, int signal) DNB_EXPORT;
-nub_bool_t DNBProcessInterrupt (nub_process_t pid) DNB_EXPORT;
-nub_bool_t DNBProcessKill (nub_process_t pid) DNB_EXPORT;
-nub_bool_t DNBProcessSendEvent (nub_process_t pid, const char *event) DNB_EXPORT;
-nub_size_t DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf) DNB_EXPORT;
-uint64_t DNBProcessMemoryReadInteger (nub_process_t pid, nub_addr_t addr, nub_size_t integer_size, uint64_t fail_value) DNB_EXPORT;
-nub_addr_t DNBProcessMemoryReadPointer (nub_process_t pid, nub_addr_t addr) DNB_EXPORT;
-std::string DNBProcessMemoryReadCString (nub_process_t pid, nub_addr_t addr) DNB_EXPORT;
-std::string DNBProcessMemoryReadCStringFixed (nub_process_t pid, nub_addr_t addr, nub_size_t fixed_length) DNB_EXPORT;
-nub_size_t DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf) DNB_EXPORT;
-nub_addr_t DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions) DNB_EXPORT;
-nub_bool_t DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr) DNB_EXPORT;
-int DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info) DNB_EXPORT;
-std::string DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType) DNB_EXPORT;
-nub_bool_t DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type) DNB_EXPORT;
+nub_bool_t DNBProcessResume(nub_process_t pid,
+ const DNBThreadResumeAction *actions,
+ size_t num_actions) DNB_EXPORT;
+nub_bool_t DNBProcessHalt(nub_process_t pid) DNB_EXPORT;
+nub_bool_t DNBProcessDetach(nub_process_t pid) DNB_EXPORT;
+nub_bool_t DNBProcessSignal(nub_process_t pid, int signal) DNB_EXPORT;
+nub_bool_t DNBProcessInterrupt(nub_process_t pid) DNB_EXPORT;
+nub_bool_t DNBProcessKill(nub_process_t pid) DNB_EXPORT;
+nub_bool_t DNBProcessSendEvent(nub_process_t pid, const char *event) DNB_EXPORT;
+nub_size_t DNBProcessMemoryRead(nub_process_t pid, nub_addr_t addr,
+ nub_size_t size, void *buf) DNB_EXPORT;
+uint64_t DNBProcessMemoryReadInteger(nub_process_t pid, nub_addr_t addr,
+ nub_size_t integer_size,
+ uint64_t fail_value) DNB_EXPORT;
+nub_addr_t DNBProcessMemoryReadPointer(nub_process_t pid,
+ nub_addr_t addr) DNB_EXPORT;
+std::string DNBProcessMemoryReadCString(nub_process_t pid,
+ nub_addr_t addr) DNB_EXPORT;
+std::string
+DNBProcessMemoryReadCStringFixed(nub_process_t pid, nub_addr_t addr,
+ nub_size_t fixed_length) DNB_EXPORT;
+nub_size_t DNBProcessMemoryWrite(nub_process_t pid, nub_addr_t addr,
+ nub_size_t size, const void *buf) DNB_EXPORT;
+nub_addr_t DNBProcessMemoryAllocate(nub_process_t pid, nub_size_t size,
+ uint32_t permissions) DNB_EXPORT;
+nub_bool_t DNBProcessMemoryDeallocate(nub_process_t pid,
+ nub_addr_t addr) DNB_EXPORT;
+int DNBProcessMemoryRegionInfo(nub_process_t pid, nub_addr_t addr,
+ DNBRegionInfo *region_info) DNB_EXPORT;
+std::string
+DNBProcessGetProfileData(nub_process_t pid,
+ DNBProfileDataScanType scanType) DNB_EXPORT;
+nub_bool_t
+DNBProcessSetEnableAsyncProfiling(nub_process_t pid, nub_bool_t enable,
+ uint64_t interval_usec,
+ DNBProfileDataScanType scan_type) DNB_EXPORT;
DarwinLogEventVector DNBProcessGetAvailableDarwinLogEvents(nub_process_t pid);
-
//----------------------------------------------------------------------
// Process status
//----------------------------------------------------------------------
-nub_bool_t DNBProcessIsAlive (nub_process_t pid) DNB_EXPORT;
-nub_state_t DNBProcessGetState (nub_process_t pid) DNB_EXPORT;
-nub_bool_t DNBProcessGetExitStatus (nub_process_t pid, int *status) DNB_EXPORT;
-nub_bool_t DNBProcessSetExitStatus (nub_process_t pid, int status) DNB_EXPORT;
-const char * DNBProcessGetExitInfo (nub_process_t pid) DNB_EXPORT;
-nub_bool_t DNBProcessSetExitInfo (nub_process_t pid, const char *info) DNB_EXPORT;
-nub_size_t DNBProcessGetNumThreads (nub_process_t pid) DNB_EXPORT;
-nub_thread_t DNBProcessGetCurrentThread (nub_process_t pid) DNB_EXPORT;
-nub_thread_t DNBProcessGetCurrentThreadMachPort (nub_process_t pid) DNB_EXPORT;
-nub_thread_t DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid) DNB_EXPORT;
-nub_thread_t DNBProcessGetThreadAtIndex (nub_process_t pid, nub_size_t thread_idx) DNB_EXPORT;
-nub_bool_t DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid) DNB_EXPORT;
-nub_addr_t DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid) DNB_EXPORT;
-nub_bool_t DNBProcessSharedLibrariesUpdated (nub_process_t pid) DNB_EXPORT;
-nub_size_t DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, DNBExecutableImageInfo **image_infos) DNB_EXPORT;
-nub_bool_t DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton) DNB_EXPORT;
-nub_bool_t DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton) DNB_EXPORT;
-nub_addr_t DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib) DNB_EXPORT;
-nub_size_t DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size) DNB_EXPORT;
-nub_size_t DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size) DNB_EXPORT;
-nub_size_t DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size) DNB_EXPORT;
-nub_size_t DNBProcessGetStopCount (nub_process_t pid) DNB_EXPORT;
-uint32_t DNBProcessGetCPUType (nub_process_t pid) DNB_EXPORT;
+nub_bool_t DNBProcessIsAlive(nub_process_t pid) DNB_EXPORT;
+nub_state_t DNBProcessGetState(nub_process_t pid) DNB_EXPORT;
+nub_bool_t DNBProcessGetExitStatus(nub_process_t pid, int *status) DNB_EXPORT;
+nub_bool_t DNBProcessSetExitStatus(nub_process_t pid, int status) DNB_EXPORT;
+const char *DNBProcessGetExitInfo(nub_process_t pid) DNB_EXPORT;
+nub_bool_t DNBProcessSetExitInfo(nub_process_t pid,
+ const char *info) DNB_EXPORT;
+nub_size_t DNBProcessGetNumThreads(nub_process_t pid) DNB_EXPORT;
+nub_thread_t DNBProcessGetCurrentThread(nub_process_t pid) DNB_EXPORT;
+nub_thread_t DNBProcessGetCurrentThreadMachPort(nub_process_t pid) DNB_EXPORT;
+nub_thread_t DNBProcessSetCurrentThread(nub_process_t pid,
+ nub_thread_t tid) DNB_EXPORT;
+nub_thread_t DNBProcessGetThreadAtIndex(nub_process_t pid,
+ nub_size_t thread_idx) DNB_EXPORT;
+nub_bool_t DNBProcessSyncThreadState(nub_process_t pid,
+ nub_thread_t tid) DNB_EXPORT;
+nub_addr_t DNBProcessGetSharedLibraryInfoAddress(nub_process_t pid) DNB_EXPORT;
+nub_bool_t DNBProcessSharedLibrariesUpdated(nub_process_t pid) DNB_EXPORT;
+nub_size_t
+DNBProcessGetSharedLibraryInfo(nub_process_t pid, nub_bool_t only_changed,
+ DNBExecutableImageInfo **image_infos) DNB_EXPORT;
+nub_bool_t DNBProcessSetNameToAddressCallback(nub_process_t pid,
+ DNBCallbackNameToAddress callback,
+ void *baton) DNB_EXPORT;
+nub_bool_t DNBProcessSetSharedLibraryInfoCallback(
+ nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback,
+ void *baton) DNB_EXPORT;
+nub_addr_t DNBProcessLookupAddress(nub_process_t pid, const char *name,
+ const char *shlib) DNB_EXPORT;
+nub_size_t DNBProcessGetAvailableSTDOUT(nub_process_t pid, char *buf,
+ nub_size_t buf_size) DNB_EXPORT;
+nub_size_t DNBProcessGetAvailableSTDERR(nub_process_t pid, char *buf,
+ nub_size_t buf_size) DNB_EXPORT;
+nub_size_t DNBProcessGetAvailableProfileData(nub_process_t pid, char *buf,
+ nub_size_t buf_size) DNB_EXPORT;
+nub_size_t DNBProcessGetStopCount(nub_process_t pid) DNB_EXPORT;
+uint32_t DNBProcessGetCPUType(nub_process_t pid) DNB_EXPORT;
//----------------------------------------------------------------------
// Process executable and arguments
//----------------------------------------------------------------------
-const char * DNBProcessGetExecutablePath (nub_process_t pid);
-const char * DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx);
-nub_size_t DNBProcessGetArgumentCount (nub_process_t pid);
+const char *DNBProcessGetExecutablePath(nub_process_t pid);
+const char *DNBProcessGetArgumentAtIndex(nub_process_t pid, nub_size_t idx);
+nub_size_t DNBProcessGetArgumentCount(nub_process_t pid);
//----------------------------------------------------------------------
// Process events
//----------------------------------------------------------------------
-nub_event_t DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout);
-void DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask);
+nub_event_t DNBProcessWaitForEvents(nub_process_t pid, nub_event_t event_mask,
+ bool wait_for_set,
+ struct timespec *timeout);
+void DNBProcessResetEvents(nub_process_t pid, nub_event_t event_mask);
//----------------------------------------------------------------------
// Thread functions
//----------------------------------------------------------------------
-const char * DNBThreadGetName (nub_process_t pid, nub_thread_t tid);
-nub_bool_t DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info);
-nub_state_t DNBThreadGetState (nub_process_t pid, nub_thread_t tid);
-nub_bool_t DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value);
-nub_bool_t DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value);
-nub_size_t DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len);
-nub_size_t DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len);
-uint32_t DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid);
-nub_bool_t DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id);
-nub_bool_t DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t set, const char *name, DNBRegisterValue *value);
-nub_bool_t DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, DNBThreadStopInfo *stop_info);
-const char * DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid);
-Genealogy::ThreadActivitySP DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out);
-Genealogy::ProcessExecutableInfoSP DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx);
-ThreadInfo::QoS DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index);
-nub_addr_t DNBGetPThreadT (nub_process_t pid, nub_thread_t tid);
-nub_addr_t DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid);
-nub_addr_t DNBGetTSDAddressForThread (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);
-JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count);
-JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos (nub_process_t pid);
-JSONGenerator::ObjectSP DNBGetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses);
-JSONGenerator::ObjectSP DNBGetSharedCacheInfo (nub_process_t pid);
+const char *DNBThreadGetName(nub_process_t pid, nub_thread_t tid);
+nub_bool_t
+DNBThreadGetIdentifierInfo(nub_process_t pid, nub_thread_t tid,
+ thread_identifier_info_data_t *ident_info);
+nub_state_t DNBThreadGetState(nub_process_t pid, nub_thread_t tid);
+nub_bool_t DNBThreadGetRegisterValueByID(nub_process_t pid, nub_thread_t tid,
+ uint32_t set, uint32_t reg,
+ DNBRegisterValue *value);
+nub_bool_t DNBThreadSetRegisterValueByID(nub_process_t pid, nub_thread_t tid,
+ uint32_t set, uint32_t reg,
+ const DNBRegisterValue *value);
+nub_size_t DNBThreadGetRegisterContext(nub_process_t pid, nub_thread_t tid,
+ void *buf, size_t buf_len);
+nub_size_t DNBThreadSetRegisterContext(nub_process_t pid, nub_thread_t tid,
+ const void *buf, size_t buf_len);
+uint32_t DNBThreadSaveRegisterState(nub_process_t pid, nub_thread_t tid);
+nub_bool_t DNBThreadRestoreRegisterState(nub_process_t pid, nub_thread_t tid,
+ uint32_t save_id);
+nub_bool_t DNBThreadGetRegisterValueByName(nub_process_t pid, nub_thread_t tid,
+ uint32_t set, const char *name,
+ DNBRegisterValue *value);
+nub_bool_t DNBThreadGetStopReason(nub_process_t pid, nub_thread_t tid,
+ DNBThreadStopInfo *stop_info);
+const char *DNBThreadGetInfo(nub_process_t pid, nub_thread_t tid);
+Genealogy::ThreadActivitySP DNBGetGenealogyInfoForThread(nub_process_t pid,
+ nub_thread_t tid,
+ bool &timed_out);
+Genealogy::ProcessExecutableInfoSP DNBGetGenealogyImageInfo(nub_process_t pid,
+ size_t idx);
+ThreadInfo::QoS DNBGetRequestedQoSForThread(nub_process_t pid, nub_thread_t tid,
+ nub_addr_t tsd,
+ uint64_t dti_qos_class_index);
+nub_addr_t DNBGetPThreadT(nub_process_t pid, nub_thread_t tid);
+nub_addr_t DNBGetDispatchQueueT(nub_process_t pid, nub_thread_t tid);
+nub_addr_t
+DNBGetTSDAddressForThread(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);
+JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos(
+ nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count);
+JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos(nub_process_t pid);
+JSONGenerator::ObjectSP
+DNBGetLibrariesInfoForAddresses(nub_process_t pid,
+ std::vector<uint64_t> &macho_addresses);
+JSONGenerator::ObjectSP DNBGetSharedCacheInfo(nub_process_t pid);
//
//----------------------------------------------------------------------
// Breakpoint functions
//----------------------------------------------------------------------
-nub_bool_t DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware);
-nub_bool_t DNBBreakpointClear (nub_process_t pid, nub_addr_t addr);
+nub_bool_t DNBBreakpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size,
+ nub_bool_t hardware);
+nub_bool_t DNBBreakpointClear(nub_process_t pid, nub_addr_t addr);
//----------------------------------------------------------------------
// Watchpoint functions
//----------------------------------------------------------------------
-nub_bool_t DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware);
-nub_bool_t DNBWatchpointClear (nub_process_t pid, nub_addr_t addr);
-uint32_t DNBWatchpointGetNumSupportedHWP (nub_process_t pid);
-
-uint32_t DNBGetRegisterCPUType ();
-const DNBRegisterSetInfo *
- DNBGetRegisterSetInfo (nub_size_t *num_reg_sets);
-nub_bool_t DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info);
+nub_bool_t DNBWatchpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size,
+ uint32_t watch_flags, nub_bool_t hardware);
+nub_bool_t DNBWatchpointClear(nub_process_t pid, nub_addr_t addr);
+uint32_t DNBWatchpointGetNumSupportedHWP(nub_process_t pid);
+
+uint32_t DNBGetRegisterCPUType();
+const DNBRegisterSetInfo *DNBGetRegisterSetInfo(nub_size_t *num_reg_sets);
+nub_bool_t DNBGetRegisterInfoByName(const char *reg_name,
+ DNBRegisterInfo *info);
//----------------------------------------------------------------------
// Other static nub information calls.
//----------------------------------------------------------------------
-const char * DNBStateAsString (nub_state_t state);
-nub_bool_t DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size);
-bool DNBGetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch);
+const char *DNBStateAsString(nub_state_t state);
+nub_bool_t DNBResolveExecutablePath(const char *path, char *resolved_path,
+ size_t resolved_path_size);
+bool DNBGetOSVersionNumbers(uint64_t *major, uint64_t *minor, uint64_t *patch);
#endif
Modified: lldb/trunk/tools/debugserver/source/DNBArch.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBArch.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBArch.cpp (original)
+++ lldb/trunk/tools/debugserver/source/DNBArch.cpp Tue Sep 6 15:57:50 2016
@@ -24,74 +24,57 @@ typedef std::map<uint32_t, DNBArchPlugin
static uint32_t g_current_cpu_type = 0;
CPUPluginInfoMap g_arch_plugins;
-
-static const DNBArchPluginInfo *
-GetArchInfo ()
-{
- CPUPluginInfoMap::const_iterator pos = g_arch_plugins.find(g_current_cpu_type);
- if (pos != g_arch_plugins.end())
- return &pos->second;
- return NULL;
-}
-
-
-uint32_t
-DNBArchProtocol::GetArchitecture ()
-{
- return g_current_cpu_type;
-}
-
-bool
-DNBArchProtocol::SetArchitecture (uint32_t cpu_type)
-{
- g_current_cpu_type = cpu_type;
- bool result = g_arch_plugins.find(g_current_cpu_type) != g_arch_plugins.end();
- DNBLogThreadedIf (LOG_PROCESS, "DNBArchProtocol::SetDefaultArchitecture (cpu_type=0x%8.8x) => %i", cpu_type, result);
- return result;
-}
-
-void
-DNBArchProtocol::RegisterArchPlugin (const DNBArchPluginInfo &arch_info)
-{
- if (arch_info.cpu_type)
- g_arch_plugins[arch_info.cpu_type] = arch_info;
-}
-
-uint32_t
-DNBArchProtocol::GetRegisterCPUType ()
-{
- const DNBArchPluginInfo *arch_info = GetArchInfo ();
- if (arch_info)
- return arch_info->cpu_type;
- return 0;
+static const DNBArchPluginInfo *GetArchInfo() {
+ CPUPluginInfoMap::const_iterator pos =
+ g_arch_plugins.find(g_current_cpu_type);
+ if (pos != g_arch_plugins.end())
+ return &pos->second;
+ return NULL;
+}
+
+uint32_t DNBArchProtocol::GetArchitecture() { return g_current_cpu_type; }
+
+bool DNBArchProtocol::SetArchitecture(uint32_t cpu_type) {
+ g_current_cpu_type = cpu_type;
+ bool result = g_arch_plugins.find(g_current_cpu_type) != g_arch_plugins.end();
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "DNBArchProtocol::SetDefaultArchitecture (cpu_type=0x%8.8x) => %i",
+ cpu_type, result);
+ return result;
+}
+
+void DNBArchProtocol::RegisterArchPlugin(const DNBArchPluginInfo &arch_info) {
+ if (arch_info.cpu_type)
+ g_arch_plugins[arch_info.cpu_type] = arch_info;
+}
+
+uint32_t DNBArchProtocol::GetRegisterCPUType() {
+ const DNBArchPluginInfo *arch_info = GetArchInfo();
+ if (arch_info)
+ return arch_info->cpu_type;
+ return 0;
}
const DNBRegisterSetInfo *
-DNBArchProtocol::GetRegisterSetInfo (nub_size_t *num_reg_sets)
-{
- const DNBArchPluginInfo *arch_info = GetArchInfo ();
- if (arch_info)
- return arch_info->GetRegisterSetInfo (num_reg_sets);
- *num_reg_sets = 0;
- return NULL;
-}
-
-DNBArchProtocol *
-DNBArchProtocol::Create (MachThread *thread)
-{
- const DNBArchPluginInfo *arch_info = GetArchInfo ();
- if (arch_info)
- return arch_info->Create (thread);
- return NULL;
-
-}
-
-const uint8_t *
-DNBArchProtocol::GetBreakpointOpcode (nub_size_t byte_size)
-{
- const DNBArchPluginInfo *arch_info = GetArchInfo ();
- if (arch_info)
- return arch_info->GetBreakpointOpcode (byte_size);
- return NULL;
+DNBArchProtocol::GetRegisterSetInfo(nub_size_t *num_reg_sets) {
+ const DNBArchPluginInfo *arch_info = GetArchInfo();
+ if (arch_info)
+ return arch_info->GetRegisterSetInfo(num_reg_sets);
+ *num_reg_sets = 0;
+ return NULL;
+}
+
+DNBArchProtocol *DNBArchProtocol::Create(MachThread *thread) {
+ const DNBArchPluginInfo *arch_info = GetArchInfo();
+ if (arch_info)
+ return arch_info->Create(thread);
+ return NULL;
+}
+
+const uint8_t *DNBArchProtocol::GetBreakpointOpcode(nub_size_t byte_size) {
+ const DNBArchPluginInfo *arch_info = GetArchInfo();
+ if (arch_info)
+ return arch_info->GetBreakpointOpcode(byte_size);
+ return NULL;
}
-
Modified: lldb/trunk/tools/debugserver/source/DNBArch.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBArch.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBArch.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBArch.h Tue Sep 6 15:57:50 2016
@@ -25,105 +25,103 @@ struct DNBRegisterSetInfo;
class DNBArchProtocol;
class MachThread;
-typedef DNBArchProtocol * (* DNBArchCallbackCreate)(MachThread *thread);
-typedef const DNBRegisterSetInfo * (* DNBArchCallbackGetRegisterSetInfo)(nub_size_t *num_reg_sets);
-typedef const uint8_t * (* DNBArchCallbackGetBreakpointOpcode)(nub_size_t byte_size);
-
-typedef struct DNBArchPluginInfoTag
-{
- uint32_t cpu_type;
- DNBArchCallbackCreate Create;
- DNBArchCallbackGetRegisterSetInfo GetRegisterSetInfo;
- DNBArchCallbackGetBreakpointOpcode GetBreakpointOpcode;
+typedef DNBArchProtocol *(*DNBArchCallbackCreate)(MachThread *thread);
+typedef const DNBRegisterSetInfo *(*DNBArchCallbackGetRegisterSetInfo)(
+ nub_size_t *num_reg_sets);
+typedef const uint8_t *(*DNBArchCallbackGetBreakpointOpcode)(
+ nub_size_t byte_size);
+
+typedef struct DNBArchPluginInfoTag {
+ uint32_t cpu_type;
+ DNBArchCallbackCreate Create;
+ DNBArchCallbackGetRegisterSetInfo GetRegisterSetInfo;
+ DNBArchCallbackGetBreakpointOpcode GetBreakpointOpcode;
} DNBArchPluginInfo;
-class DNBArchProtocol
-{
+class DNBArchProtocol {
public:
- static DNBArchProtocol *
- Create (MachThread *thread);
+ static DNBArchProtocol *Create(MachThread *thread);
- static uint32_t
- GetRegisterCPUType ();
+ static uint32_t GetRegisterCPUType();
- static const DNBRegisterSetInfo *
- GetRegisterSetInfo (nub_size_t *num_reg_sets);
+ static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets);
- static const uint8_t *
- GetBreakpointOpcode (nub_size_t byte_size);
-
- static void
- RegisterArchPlugin (const DNBArchPluginInfo &arch_info);
-
- static uint32_t
- GetArchitecture ();
-
- static bool
- SetArchitecture (uint32_t cpu_type);
-
- DNBArchProtocol () :
- m_save_id(0)
- {
-
- }
-
- virtual ~DNBArchProtocol ()
- {
-
- }
- virtual bool GetRegisterValue (uint32_t set, uint32_t reg, DNBRegisterValue *value) = 0;
- virtual bool SetRegisterValue (uint32_t set, uint32_t reg, const DNBRegisterValue *value) = 0;
- virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len) = 0;
- virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len) = 0;
- virtual uint32_t SaveRegisterState () = 0;
- virtual bool RestoreRegisterState (uint32_t save_id) = 0;
-
- virtual kern_return_t GetRegisterState (int set, bool force) = 0;
- virtual kern_return_t SetRegisterState (int set) = 0;
- virtual bool RegisterSetStateIsValid (int set) const = 0;
-
- virtual uint64_t GetPC (uint64_t failValue) = 0; // Get program counter
- virtual kern_return_t SetPC (uint64_t value) = 0;
- virtual uint64_t GetSP (uint64_t failValue) = 0; // Get stack pointer
- virtual void ThreadWillResume () = 0;
- virtual bool ThreadDidStop () = 0;
- virtual bool NotifyException (MachException::Data& exc) { return false; }
- virtual uint32_t NumSupportedHardwareBreakpoints() { return 0; }
- virtual uint32_t NumSupportedHardwareWatchpoints() { return 0; }
- virtual uint32_t EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size) { return INVALID_NUB_HW_INDEX; }
- virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task) { return INVALID_NUB_HW_INDEX; }
- virtual bool DisableHardwareBreakpoint (uint32_t hw_index) { return false; }
- virtual bool DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task) { return false; }
- virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr) { return INVALID_NUB_HW_INDEX; }
- virtual bool StepNotComplete () { return false; }
+ static const uint8_t *GetBreakpointOpcode(nub_size_t byte_size);
+
+ static void RegisterArchPlugin(const DNBArchPluginInfo &arch_info);
+
+ static uint32_t GetArchitecture();
+
+ static bool SetArchitecture(uint32_t cpu_type);
+
+ DNBArchProtocol() : m_save_id(0) {}
+
+ virtual ~DNBArchProtocol() {}
+ virtual bool GetRegisterValue(uint32_t set, uint32_t reg,
+ DNBRegisterValue *value) = 0;
+ virtual bool SetRegisterValue(uint32_t set, uint32_t reg,
+ const DNBRegisterValue *value) = 0;
+ virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len) = 0;
+ virtual nub_size_t SetRegisterContext(const void *buf,
+ nub_size_t buf_len) = 0;
+ virtual uint32_t SaveRegisterState() = 0;
+ virtual bool RestoreRegisterState(uint32_t save_id) = 0;
+
+ virtual kern_return_t GetRegisterState(int set, bool force) = 0;
+ virtual kern_return_t SetRegisterState(int set) = 0;
+ virtual bool RegisterSetStateIsValid(int set) const = 0;
+
+ virtual uint64_t GetPC(uint64_t failValue) = 0; // Get program counter
+ virtual kern_return_t SetPC(uint64_t value) = 0;
+ virtual uint64_t GetSP(uint64_t failValue) = 0; // Get stack pointer
+ virtual void ThreadWillResume() = 0;
+ virtual bool ThreadDidStop() = 0;
+ virtual bool NotifyException(MachException::Data &exc) { return false; }
+ virtual uint32_t NumSupportedHardwareBreakpoints() { return 0; }
+ virtual uint32_t NumSupportedHardwareWatchpoints() { return 0; }
+ virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size) {
+ return INVALID_NUB_HW_INDEX;
+ }
+ virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size,
+ bool read, bool write,
+ bool also_set_on_task) {
+ return INVALID_NUB_HW_INDEX;
+ }
+ virtual bool DisableHardwareBreakpoint(uint32_t hw_index) { return false; }
+ virtual bool DisableHardwareWatchpoint(uint32_t hw_index,
+ bool also_set_on_task) {
+ return false;
+ }
+ virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr) {
+ return INVALID_NUB_HW_INDEX;
+ }
+ virtual bool StepNotComplete() { return false; }
protected:
- friend class MachThread;
+ friend class MachThread;
- uint32_t GetNextRegisterStateSaveID ()
- {
- return ++m_save_id;
- }
-
- enum
- {
- Trans_Pending = 0, // Transaction is pending, and checkpoint state has been snapshotted.
- Trans_Done = 1, // Transaction is done, the current state is committed, and checkpoint state is irrelevant.
- Trans_Rolled_Back = 2 // Transaction is done, the current state has been rolled back to the checkpoint state.
- };
- virtual bool StartTransForHWP() { return true; }
- virtual bool RollbackTransForHWP() { return true; }
- virtual bool FinishTransForHWP() { return true; }
-
- uint32_t m_save_id; // An always incrementing integer ID used with SaveRegisterState/RestoreRegisterState
+ uint32_t GetNextRegisterStateSaveID() { return ++m_save_id; }
-};
+ enum {
+ Trans_Pending =
+ 0, // Transaction is pending, and checkpoint state has been snapshotted.
+ Trans_Done = 1, // Transaction is done, the current state is committed, and
+ // checkpoint state is irrelevant.
+ Trans_Rolled_Back = 2 // Transaction is done, the current state has been
+ // rolled back to the checkpoint state.
+ };
+ virtual bool StartTransForHWP() { return true; }
+ virtual bool RollbackTransForHWP() { return true; }
+ virtual bool FinishTransForHWP() { return true; }
+ uint32_t m_save_id; // An always incrementing integer ID used with
+ // SaveRegisterState/RestoreRegisterState
+};
#include "MacOSX/arm/DNBArchImpl.h"
#include "MacOSX/arm64/DNBArchImplARM64.h"
#include "MacOSX/i386/DNBArchImplI386.h"
-#include "MacOSX/x86_64/DNBArchImplX86_64.h"
#include "MacOSX/ppc/DNBArchImpl.h"
+#include "MacOSX/x86_64/DNBArchImplX86_64.h"
#endif
Modified: lldb/trunk/tools/debugserver/source/DNBBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBBreakpoint.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBBreakpoint.cpp (original)
+++ lldb/trunk/tools/debugserver/source/DNBBreakpoint.cpp Tue Sep 6 15:57:50 2016
@@ -12,214 +12,167 @@
//===----------------------------------------------------------------------===//
#include "DNBBreakpoint.h"
+#include "DNBLog.h"
#include "MachProcess.h"
-#include <assert.h>
#include <algorithm>
+#include <assert.h>
#include <inttypes.h>
-#include "DNBLog.h"
+#pragma mark-- DNBBreakpoint
+DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size,
+ bool hardware)
+ : m_retain_count(1), m_byte_size(static_cast<uint32_t>(byte_size)),
+ m_opcode(), m_addr(addr), m_enabled(0), m_hw_preferred(hardware),
+ m_is_watchpoint(0), m_watch_read(0), m_watch_write(0),
+ m_hw_index(INVALID_NUB_HW_INDEX) {}
+
+DNBBreakpoint::~DNBBreakpoint() {}
+
+void DNBBreakpoint::Dump() const {
+ if (IsBreakpoint()) {
+ DNBLog("DNBBreakpoint addr = 0x%llx state = %s type = %s breakpoint "
+ "hw_index = %i",
+ (uint64_t)m_addr, m_enabled ? "enabled " : "disabled",
+ IsHardware() ? "hardware" : "software", GetHardwareIndex());
+ } else {
+ DNBLog("DNBBreakpoint addr = 0x%llx size = %llu state = %s type = %s "
+ "watchpoint (%s%s) hw_index = %i",
+ (uint64_t)m_addr, (uint64_t)m_byte_size,
+ m_enabled ? "enabled " : "disabled",
+ IsHardware() ? "hardware" : "software", m_watch_read ? "r" : "",
+ m_watch_write ? "w" : "", GetHardwareIndex());
+ }
+}
+
+#pragma mark-- DNBBreakpointList
+
+DNBBreakpointList::DNBBreakpointList() {}
+
+DNBBreakpointList::~DNBBreakpointList() {}
+
+DNBBreakpoint *DNBBreakpointList::Add(nub_addr_t addr, nub_size_t length,
+ bool hardware) {
+ m_breakpoints.insert(
+ std::make_pair(addr, DNBBreakpoint(addr, length, hardware)));
+ iterator pos = m_breakpoints.find(addr);
+ return &pos->second;
+}
+
+bool DNBBreakpointList::Remove(nub_addr_t addr) {
+ iterator pos = m_breakpoints.find(addr);
+ if (pos != m_breakpoints.end()) {
+ m_breakpoints.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+DNBBreakpoint *DNBBreakpointList::FindByAddress(nub_addr_t addr) {
+ iterator pos = m_breakpoints.find(addr);
+ if (pos != m_breakpoints.end())
+ return &pos->second;
-#pragma mark -- DNBBreakpoint
-DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, bool hardware) :
- m_retain_count (1),
- m_byte_size (static_cast<uint32_t>(byte_size)),
- m_opcode(),
- m_addr(addr),
- m_enabled(0),
- m_hw_preferred(hardware),
- m_is_watchpoint(0),
- m_watch_read(0),
- m_watch_write(0),
- m_hw_index(INVALID_NUB_HW_INDEX)
-{
-}
-
-DNBBreakpoint::~DNBBreakpoint()
-{
-}
-
-void
-DNBBreakpoint::Dump() const
-{
- if (IsBreakpoint())
- {
- DNBLog ("DNBBreakpoint addr = 0x%llx state = %s type = %s breakpoint hw_index = %i",
- (uint64_t)m_addr,
- m_enabled ? "enabled " : "disabled",
- IsHardware() ? "hardware" : "software",
- GetHardwareIndex());
- }
- else
- {
- DNBLog ("DNBBreakpoint addr = 0x%llx size = %llu state = %s type = %s watchpoint (%s%s) hw_index = %i",
- (uint64_t)m_addr,
- (uint64_t)m_byte_size,
- m_enabled ? "enabled " : "disabled",
- IsHardware() ? "hardware" : "software",
- m_watch_read ? "r" : "",
- m_watch_write ? "w" : "",
- GetHardwareIndex());
- }
-}
-
-#pragma mark -- DNBBreakpointList
-
-DNBBreakpointList::DNBBreakpointList()
-{
-}
-
-DNBBreakpointList::~DNBBreakpointList()
-{
+ return NULL;
}
-
-DNBBreakpoint *
-DNBBreakpointList::Add(nub_addr_t addr, nub_size_t length, bool hardware)
-{
- m_breakpoints.insert(std::make_pair(addr, DNBBreakpoint(addr, length, hardware)));
- iterator pos = m_breakpoints.find (addr);
+const DNBBreakpoint *DNBBreakpointList::FindByAddress(nub_addr_t addr) const {
+ const_iterator pos = m_breakpoints.find(addr);
+ if (pos != m_breakpoints.end())
return &pos->second;
-}
-bool
-DNBBreakpointList::Remove (nub_addr_t addr)
-{
- iterator pos = m_breakpoints.find(addr);
- if (pos != m_breakpoints.end())
- {
- m_breakpoints.erase(pos);
- return true;
- }
- return false;
-}
-
-DNBBreakpoint *
-DNBBreakpointList::FindByAddress (nub_addr_t addr)
-{
- iterator pos = m_breakpoints.find(addr);
- if (pos != m_breakpoints.end())
- return &pos->second;
-
- return NULL;
-}
-
-const DNBBreakpoint *
-DNBBreakpointList::FindByAddress (nub_addr_t addr) const
-{
- const_iterator pos = m_breakpoints.find(addr);
- if (pos != m_breakpoints.end())
- return &pos->second;
-
- return NULL;
+ return NULL;
}
// Finds the next breakpoint at an address greater than or equal to "addr"
-size_t
-DNBBreakpointList::FindBreakpointsThatOverlapRange (nub_addr_t addr,
- nub_addr_t size,
- std::vector<DNBBreakpoint *> &bps)
-{
- bps.clear();
- iterator end = m_breakpoints.end();
- // Find the first breakpoint with an address >= to "addr"
- iterator pos = m_breakpoints.lower_bound(addr);
- if (pos != end)
- {
- if (pos != m_breakpoints.begin())
- {
- // Watch out for a breakpoint at an address less than "addr" that might still overlap
- iterator prev_pos = pos;
- --prev_pos;
- if (prev_pos->second.IntersectsRange (addr, size, NULL, NULL, NULL))
- bps.push_back (&pos->second);
-
- }
-
- while (pos != end)
- {
- // When we hit a breakpoint whose start address is greater than "addr + size" we are done.
- // Do the math in a way that doesn't risk unsigned overflow with bad input.
- if ((pos->second.Address() - addr) >= size)
- break;
-
- // Check if this breakpoint overlaps, and if it does, add it to the list
- if (pos->second.IntersectsRange (addr, size, NULL, NULL, NULL))
- {
- bps.push_back (&pos->second);
- ++pos;
- }
- }
- }
- return bps.size();
-}
-
-void
-DNBBreakpointList::Dump() const
-{
- const_iterator pos;
- const_iterator end = m_breakpoints.end();
- for (pos = m_breakpoints.begin(); pos != end; ++pos)
- pos->second.Dump();
-}
-
-void
-DNBBreakpointList::DisableAll ()
-{
- iterator pos, end = m_breakpoints.end();
- for (pos = m_breakpoints.begin(); pos != end; ++pos)
- pos->second.SetEnabled(false);
-}
-
-
-void
-DNBBreakpointList::RemoveTrapsFromBuffer (nub_addr_t addr, nub_size_t size, void *p) const
-{
- uint8_t *buf = (uint8_t *)p;
- const_iterator end = m_breakpoints.end();
- const_iterator pos = m_breakpoints.lower_bound(addr);
- while (pos != end && (pos->first < (addr + size)))
- {
- nub_addr_t intersect_addr;
- nub_size_t intersect_size;
- nub_size_t opcode_offset;
- const DNBBreakpoint &bp = pos->second;
- if (bp.IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset))
- {
- assert(addr <= intersect_addr && intersect_addr < addr + size);
- assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size);
- assert(opcode_offset + intersect_size <= bp.ByteSize());
- nub_size_t buf_offset = intersect_addr - addr;
- ::memcpy(buf + buf_offset, bp.SavedOpcodeBytes() + opcode_offset, intersect_size);
- }
+size_t DNBBreakpointList::FindBreakpointsThatOverlapRange(
+ nub_addr_t addr, nub_addr_t size, std::vector<DNBBreakpoint *> &bps) {
+ bps.clear();
+ iterator end = m_breakpoints.end();
+ // Find the first breakpoint with an address >= to "addr"
+ iterator pos = m_breakpoints.lower_bound(addr);
+ if (pos != end) {
+ if (pos != m_breakpoints.begin()) {
+ // Watch out for a breakpoint at an address less than "addr" that might
+ // still overlap
+ iterator prev_pos = pos;
+ --prev_pos;
+ if (prev_pos->second.IntersectsRange(addr, size, NULL, NULL, NULL))
+ bps.push_back(&pos->second);
+ }
+
+ while (pos != end) {
+ // When we hit a breakpoint whose start address is greater than "addr +
+ // size" we are done.
+ // Do the math in a way that doesn't risk unsigned overflow with bad
+ // input.
+ if ((pos->second.Address() - addr) >= size)
+ break;
+
+ // Check if this breakpoint overlaps, and if it does, add it to the list
+ if (pos->second.IntersectsRange(addr, size, NULL, NULL, NULL)) {
+ bps.push_back(&pos->second);
++pos;
+ }
}
+ }
+ return bps.size();
}
-void
-DNBBreakpointList::DisableAllBreakpoints(MachProcess *process)
-{
- iterator pos, end = m_breakpoints.end();
- for (pos = m_breakpoints.begin(); pos != end; ++pos)
- process->DisableBreakpoint(pos->second.Address(), false);
-}
-
-void
-DNBBreakpointList::DisableAllWatchpoints(MachProcess *process)
-{
- iterator pos, end = m_breakpoints.end();
- for (pos = m_breakpoints.begin(); pos != end; ++pos)
- process->DisableWatchpoint(pos->second.Address(), false);
-}
-
-void
-DNBBreakpointList::RemoveDisabled()
-{
- iterator pos = m_breakpoints.begin();
- while (pos != m_breakpoints.end())
- {
- if (!pos->second.IsEnabled())
- pos = m_breakpoints.erase(pos);
- else
- ++pos;
- }
+void DNBBreakpointList::Dump() const {
+ const_iterator pos;
+ const_iterator end = m_breakpoints.end();
+ for (pos = m_breakpoints.begin(); pos != end; ++pos)
+ pos->second.Dump();
+}
+
+void DNBBreakpointList::DisableAll() {
+ iterator pos, end = m_breakpoints.end();
+ for (pos = m_breakpoints.begin(); pos != end; ++pos)
+ pos->second.SetEnabled(false);
+}
+
+void DNBBreakpointList::RemoveTrapsFromBuffer(nub_addr_t addr, nub_size_t size,
+ void *p) const {
+ uint8_t *buf = (uint8_t *)p;
+ const_iterator end = m_breakpoints.end();
+ const_iterator pos = m_breakpoints.lower_bound(addr);
+ while (pos != end && (pos->first < (addr + size))) {
+ nub_addr_t intersect_addr;
+ nub_size_t intersect_size;
+ nub_size_t opcode_offset;
+ const DNBBreakpoint &bp = pos->second;
+ if (bp.IntersectsRange(addr, size, &intersect_addr, &intersect_size,
+ &opcode_offset)) {
+ assert(addr <= intersect_addr && intersect_addr < addr + size);
+ assert(addr < intersect_addr + intersect_size &&
+ intersect_addr + intersect_size <= addr + size);
+ assert(opcode_offset + intersect_size <= bp.ByteSize());
+ nub_size_t buf_offset = intersect_addr - addr;
+ ::memcpy(buf + buf_offset, bp.SavedOpcodeBytes() + opcode_offset,
+ intersect_size);
+ }
+ ++pos;
+ }
+}
+
+void DNBBreakpointList::DisableAllBreakpoints(MachProcess *process) {
+ iterator pos, end = m_breakpoints.end();
+ for (pos = m_breakpoints.begin(); pos != end; ++pos)
+ process->DisableBreakpoint(pos->second.Address(), false);
+}
+
+void DNBBreakpointList::DisableAllWatchpoints(MachProcess *process) {
+ iterator pos, end = m_breakpoints.end();
+ for (pos = m_breakpoints.begin(); pos != end; ++pos)
+ process->DisableWatchpoint(pos->second.Address(), false);
+}
+
+void DNBBreakpointList::RemoveDisabled() {
+ iterator pos = m_breakpoints.begin();
+ while (pos != m_breakpoints.end()) {
+ if (!pos->second.IsEnabled())
+ pos = m_breakpoints.erase(pos);
+ else
+ ++pos;
+ }
}
Modified: lldb/trunk/tools/debugserver/source/DNBBreakpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBBreakpoint.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBBreakpoint.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBBreakpoint.h Tue Sep 6 15:57:50 2016
@@ -23,143 +23,127 @@
class MachProcess;
-class DNBBreakpoint
-{
+class DNBBreakpoint {
public:
- DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, bool hardware);
- ~DNBBreakpoint();
+ DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, bool hardware);
+ ~DNBBreakpoint();
- nub_size_t ByteSize() const { return m_byte_size; }
- uint8_t * SavedOpcodeBytes() { return &m_opcode[0]; }
- const uint8_t *
- SavedOpcodeBytes() const { return &m_opcode[0]; }
- nub_addr_t Address() const { return m_addr; }
-// nub_thread_t ThreadID() const { return m_tid; }
- bool IsEnabled() const { return m_enabled; }
- bool IntersectsRange(nub_addr_t addr,
- nub_size_t size,
- nub_addr_t *intersect_addr,
- nub_size_t *intersect_size,
- nub_size_t *opcode_offset) const
- {
- // We only use software traps for software breakpoints
- if (IsBreakpoint() && IsEnabled() && !IsHardware())
- {
- if (m_byte_size > 0)
- {
- const nub_addr_t bp_end_addr = m_addr + m_byte_size;
- const nub_addr_t end_addr = addr + size;
- // Is the breakpoint end address before the passed in start address?
- if (bp_end_addr <= addr)
- return false;
- // Is the breakpoint start address after passed in end address?
- if (end_addr <= m_addr)
- return false;
- if (intersect_addr || intersect_size || opcode_offset)
- {
- if (m_addr < addr)
- {
- if (intersect_addr)
- *intersect_addr = addr;
- if (intersect_size)
- *intersect_size = std::min<nub_addr_t>(bp_end_addr, end_addr) - addr;
- if (opcode_offset)
- *opcode_offset = addr - m_addr;
- }
- else
- {
- if (intersect_addr)
- *intersect_addr = m_addr;
- if (intersect_size)
- *intersect_size = std::min<nub_addr_t>(bp_end_addr, end_addr) - m_addr;
- if (opcode_offset)
- *opcode_offset = 0;
- }
- }
- return true;
- }
- }
- return false;
- }
- void SetEnabled(bool enabled)
- {
- if (!enabled)
- SetHardwareIndex(INVALID_NUB_HW_INDEX);
- m_enabled = enabled;
- }
- void SetIsWatchpoint (uint32_t type)
- {
- m_is_watchpoint = 1;
- m_watch_read = (type & WATCH_TYPE_READ) != 0;
- m_watch_write = (type & WATCH_TYPE_WRITE) != 0;
- }
- bool IsBreakpoint() const { return m_is_watchpoint == 0; }
- bool IsWatchpoint() const { return m_is_watchpoint == 1; }
- bool WatchpointRead() const { return m_watch_read != 0; }
- bool WatchpointWrite() const { return m_watch_write != 0; }
- bool HardwarePreferred() const { return m_hw_preferred; }
- bool IsHardware() const { return m_hw_index != INVALID_NUB_HW_INDEX; }
- uint32_t GetHardwareIndex() const { return m_hw_index; }
- void SetHardwareIndex(uint32_t hw_index) { m_hw_index = hw_index; }
- void Dump() const;
- uint32_t Retain ()
- {
- return ++m_retain_count;
- }
- uint32_t Release ()
- {
- if (m_retain_count == 0)
- return 0;
- return --m_retain_count;
- }
+ nub_size_t ByteSize() const { return m_byte_size; }
+ uint8_t *SavedOpcodeBytes() { return &m_opcode[0]; }
+ const uint8_t *SavedOpcodeBytes() const { return &m_opcode[0]; }
+ nub_addr_t Address() const { return m_addr; }
+ // nub_thread_t ThreadID() const { return m_tid; }
+ bool IsEnabled() const { return m_enabled; }
+ bool IntersectsRange(nub_addr_t addr, nub_size_t size,
+ nub_addr_t *intersect_addr, nub_size_t *intersect_size,
+ nub_size_t *opcode_offset) const {
+ // We only use software traps for software breakpoints
+ if (IsBreakpoint() && IsEnabled() && !IsHardware()) {
+ if (m_byte_size > 0) {
+ const nub_addr_t bp_end_addr = m_addr + m_byte_size;
+ const nub_addr_t end_addr = addr + size;
+ // Is the breakpoint end address before the passed in start address?
+ if (bp_end_addr <= addr)
+ return false;
+ // Is the breakpoint start address after passed in end address?
+ if (end_addr <= m_addr)
+ return false;
+ if (intersect_addr || intersect_size || opcode_offset) {
+ if (m_addr < addr) {
+ if (intersect_addr)
+ *intersect_addr = addr;
+ if (intersect_size)
+ *intersect_size =
+ std::min<nub_addr_t>(bp_end_addr, end_addr) - addr;
+ if (opcode_offset)
+ *opcode_offset = addr - m_addr;
+ } else {
+ if (intersect_addr)
+ *intersect_addr = m_addr;
+ if (intersect_size)
+ *intersect_size =
+ std::min<nub_addr_t>(bp_end_addr, end_addr) - m_addr;
+ if (opcode_offset)
+ *opcode_offset = 0;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+ void SetEnabled(bool enabled) {
+ if (!enabled)
+ SetHardwareIndex(INVALID_NUB_HW_INDEX);
+ m_enabled = enabled;
+ }
+ void SetIsWatchpoint(uint32_t type) {
+ m_is_watchpoint = 1;
+ m_watch_read = (type & WATCH_TYPE_READ) != 0;
+ m_watch_write = (type & WATCH_TYPE_WRITE) != 0;
+ }
+ bool IsBreakpoint() const { return m_is_watchpoint == 0; }
+ bool IsWatchpoint() const { return m_is_watchpoint == 1; }
+ bool WatchpointRead() const { return m_watch_read != 0; }
+ bool WatchpointWrite() const { return m_watch_write != 0; }
+ bool HardwarePreferred() const { return m_hw_preferred; }
+ bool IsHardware() const { return m_hw_index != INVALID_NUB_HW_INDEX; }
+ uint32_t GetHardwareIndex() const { return m_hw_index; }
+ void SetHardwareIndex(uint32_t hw_index) { m_hw_index = hw_index; }
+ void Dump() const;
+ uint32_t Retain() { return ++m_retain_count; }
+ uint32_t Release() {
+ if (m_retain_count == 0)
+ return 0;
+ return --m_retain_count;
+ }
private:
- uint32_t m_retain_count; // Each breakpoint is maintained by address and is ref counted in case multiple people set a breakpoint at the same address
- uint32_t m_byte_size; // Length in bytes of the breakpoint if set in memory
- uint8_t m_opcode[8]; // Saved opcode bytes
- nub_addr_t m_addr; // Address of this breakpoint
- uint32_t m_enabled:1, // Flags for this breakpoint
- m_hw_preferred:1, // 1 if this point has been requested to be set using hardware (which may fail due to lack of resources)
- m_is_watchpoint:1, // 1 if this is a watchpoint
- m_watch_read:1, // 1 if we stop when the watched data is read from
- m_watch_write:1; // 1 if we stop when the watched data is written to
- uint32_t m_hw_index; // The hardware resource index for this breakpoint/watchpoint
+ uint32_t m_retain_count; // Each breakpoint is maintained by address and is
+ // ref counted in case multiple people set a
+ // breakpoint at the same address
+ uint32_t m_byte_size; // Length in bytes of the breakpoint if set in memory
+ uint8_t m_opcode[8]; // Saved opcode bytes
+ nub_addr_t m_addr; // Address of this breakpoint
+ uint32_t m_enabled : 1, // Flags for this breakpoint
+ m_hw_preferred : 1, // 1 if this point has been requested to be set using
+ // hardware (which may fail due to lack of resources)
+ m_is_watchpoint : 1, // 1 if this is a watchpoint
+ m_watch_read : 1, // 1 if we stop when the watched data is read from
+ m_watch_write : 1; // 1 if we stop when the watched data is written to
+ uint32_t
+ m_hw_index; // The hardware resource index for this breakpoint/watchpoint
};
-
-class DNBBreakpointList
-{
+class DNBBreakpointList {
public:
- DNBBreakpointList();
- ~DNBBreakpointList();
+ DNBBreakpointList();
+ ~DNBBreakpointList();
+
+ DNBBreakpoint *Add(nub_addr_t addr, nub_size_t length, bool hardware);
+ bool Remove(nub_addr_t addr);
+ DNBBreakpoint *FindByAddress(nub_addr_t addr);
+ const DNBBreakpoint *FindByAddress(nub_addr_t addr) const;
+
+ size_t FindBreakpointsThatOverlapRange(nub_addr_t addr, nub_addr_t size,
+ std::vector<DNBBreakpoint *> &bps);
+
+ void Dump() const;
+
+ size_t Size() const { return m_breakpoints.size(); }
+ void DisableAll();
+
+ void RemoveTrapsFromBuffer(nub_addr_t addr, nub_size_t size, void *buf) const;
+
+ void DisableAllBreakpoints(MachProcess *process);
+ void DisableAllWatchpoints(MachProcess *process);
+ void RemoveDisabled();
- DNBBreakpoint * Add (nub_addr_t addr, nub_size_t length, bool hardware);
- bool Remove (nub_addr_t addr);
- DNBBreakpoint * FindByAddress (nub_addr_t addr);
- const DNBBreakpoint * FindByAddress (nub_addr_t addr) const;
-
- size_t FindBreakpointsThatOverlapRange (nub_addr_t addr,
- nub_addr_t size,
- std::vector<DNBBreakpoint *> &bps);
-
- void Dump () const;
-
- size_t Size() const { return m_breakpoints.size(); }
- void DisableAll ();
-
- void RemoveTrapsFromBuffer (nub_addr_t addr,
- nub_size_t size,
- void *buf) const;
-
- void DisableAllBreakpoints (MachProcess *process);
- void DisableAllWatchpoints(MachProcess *process);
- void RemoveDisabled ();
protected:
- typedef std::map<nub_addr_t, DNBBreakpoint> collection;
- typedef collection::iterator iterator;
- typedef collection::const_iterator const_iterator;
- collection m_breakpoints;
+ typedef std::map<nub_addr_t, DNBBreakpoint> collection;
+ typedef collection::iterator iterator;
+ typedef collection::const_iterator const_iterator;
+ collection m_breakpoints;
};
#endif
-
Modified: lldb/trunk/tools/debugserver/source/DNBDataRef.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBDataRef.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBDataRef.cpp (original)
+++ lldb/trunk/tools/debugserver/source/DNBDataRef.cpp Tue Sep 6 15:57:50 2016
@@ -21,165 +21,139 @@
// Constructor
//----------------------------------------------------------------------
-DNBDataRef::DNBDataRef() :
- m_start(NULL),
- m_end(NULL),
- m_swap(false),
- m_ptrSize(0),
- m_addrPCRelative(INVALID_NUB_ADDRESS),
- m_addrTEXT(INVALID_NUB_ADDRESS),
- m_addrDATA(INVALID_NUB_ADDRESS)
-{
-}
-
+DNBDataRef::DNBDataRef()
+ : m_start(NULL), m_end(NULL), m_swap(false), m_ptrSize(0),
+ m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS),
+ m_addrDATA(INVALID_NUB_ADDRESS) {}
//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
-DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap) :
- m_start(start),
- m_end(start+size),
- m_swap(swap),
- m_ptrSize(0),
- m_addrPCRelative(INVALID_NUB_ADDRESS),
- m_addrTEXT(INVALID_NUB_ADDRESS),
- m_addrDATA(INVALID_NUB_ADDRESS)
-{
-}
-
+DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap)
+ : m_start(start), m_end(start + size), m_swap(swap), m_ptrSize(0),
+ m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS),
+ m_addrDATA(INVALID_NUB_ADDRESS) {}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-DNBDataRef::~DNBDataRef()
-{
-}
-
+DNBDataRef::~DNBDataRef() {}
//----------------------------------------------------------------------
// Get8
//----------------------------------------------------------------------
-uint8_t
-DNBDataRef::Get8(offset_t *offset_ptr) const
-{
- uint8_t val = 0;
- if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
- {
- val = *(m_start + *offset_ptr);
- *offset_ptr += sizeof(val);
- }
- return val;
+uint8_t DNBDataRef::Get8(offset_t *offset_ptr) const {
+ uint8_t val = 0;
+ if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
+ val = *(m_start + *offset_ptr);
+ *offset_ptr += sizeof(val);
+ }
+ return val;
}
-
//----------------------------------------------------------------------
// Get16
//----------------------------------------------------------------------
-uint16_t
-DNBDataRef::Get16(offset_t *offset_ptr) const
-{
- uint16_t val = 0;
- if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
- {
- const uint8_t *p = m_start + *offset_ptr;
- val = *(uint16_t*)p;
-
- if (m_swap)
- val = OSSwapInt16(val);
-
- // Advance the offset
- *offset_ptr += sizeof(val);
- }
- return val;
+uint16_t DNBDataRef::Get16(offset_t *offset_ptr) const {
+ uint16_t val = 0;
+ if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
+ const uint8_t *p = m_start + *offset_ptr;
+ val = *(uint16_t *)p;
+
+ if (m_swap)
+ val = OSSwapInt16(val);
+
+ // Advance the offset
+ *offset_ptr += sizeof(val);
+ }
+ return val;
}
-
//----------------------------------------------------------------------
// Get32
//----------------------------------------------------------------------
-uint32_t
-DNBDataRef::Get32(offset_t *offset_ptr) const
-{
- uint32_t val = 0;
- if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
- {
- const uint8_t *p = m_start + *offset_ptr;
- val = *(uint32_t*)p;
- if (m_swap)
- val = OSSwapInt32(val);
-
- // Advance the offset
- *offset_ptr += sizeof(val);
- }
- return val;
+uint32_t DNBDataRef::Get32(offset_t *offset_ptr) const {
+ uint32_t val = 0;
+ if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
+ const uint8_t *p = m_start + *offset_ptr;
+ val = *(uint32_t *)p;
+ if (m_swap)
+ val = OSSwapInt32(val);
+
+ // Advance the offset
+ *offset_ptr += sizeof(val);
+ }
+ return val;
}
-
//----------------------------------------------------------------------
// Get64
//----------------------------------------------------------------------
-uint64_t
-DNBDataRef::Get64(offset_t *offset_ptr) const
-{
- uint64_t val = 0;
- if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
- {
- const uint8_t *p = m_start + *offset_ptr;
- val = *(uint64_t*)p;
- if (m_swap)
- val = OSSwapInt64(val);
-
- // Advance the offset
- *offset_ptr += sizeof(val);
- }
- return val;
+uint64_t DNBDataRef::Get64(offset_t *offset_ptr) const {
+ uint64_t val = 0;
+ if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
+ const uint8_t *p = m_start + *offset_ptr;
+ val = *(uint64_t *)p;
+ if (m_swap)
+ val = OSSwapInt64(val);
+
+ // Advance the offset
+ *offset_ptr += sizeof(val);
+ }
+ return val;
}
-
//----------------------------------------------------------------------
// GetMax32
//
// Used for calls when the size can vary. Fill in extra cases if they
// are ever needed.
//----------------------------------------------------------------------
-uint32_t
-DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const
-{
- switch (byte_size)
- {
- case 1: return Get8 (offset_ptr); break;
- case 2: return Get16(offset_ptr); break;
- case 4: return Get32(offset_ptr); break;
- default:
- assert(!"GetMax32 unhandled case!");
- break;
- }
- return 0;
+uint32_t DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const {
+ switch (byte_size) {
+ case 1:
+ return Get8(offset_ptr);
+ break;
+ case 2:
+ return Get16(offset_ptr);
+ break;
+ case 4:
+ return Get32(offset_ptr);
+ break;
+ default:
+ assert(!"GetMax32 unhandled case!");
+ break;
+ }
+ return 0;
}
-
//----------------------------------------------------------------------
// GetMax64
//
// Used for calls when the size can vary. Fill in extra cases if they
// are ever needed.
//----------------------------------------------------------------------
-uint64_t
-DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const
-{
- switch (size)
- {
- case 1: return Get8 (offset_ptr); break;
- case 2: return Get16(offset_ptr); break;
- case 4: return Get32(offset_ptr); break;
- case 8: return Get64(offset_ptr); break;
- default:
- assert(!"GetMax64 unhandled case!");
- break;
- }
- return 0;
+uint64_t DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const {
+ switch (size) {
+ case 1:
+ return Get8(offset_ptr);
+ break;
+ case 2:
+ return Get16(offset_ptr);
+ break;
+ case 4:
+ return Get32(offset_ptr);
+ break;
+ case 8:
+ return Get64(offset_ptr);
+ break;
+ default:
+ assert(!"GetMax64 unhandled case!");
+ break;
+ }
+ return 0;
}
//----------------------------------------------------------------------
@@ -188,198 +162,190 @@ DNBDataRef::GetMax64(offset_t *offset_pt
// Extract a pointer value from the buffer. The pointer size must be
// set prior to using this using one of the SetPointerSize functions.
//----------------------------------------------------------------------
-uint64_t
-DNBDataRef::GetPointer(offset_t *offset_ptr) const
-{
- // Must set pointer size prior to using this call
- assert(m_ptrSize != 0);
- return GetMax64(offset_ptr, m_ptrSize);
+uint64_t DNBDataRef::GetPointer(offset_t *offset_ptr) const {
+ // Must set pointer size prior to using this call
+ assert(m_ptrSize != 0);
+ return GetMax64(offset_ptr, m_ptrSize);
}
//----------------------------------------------------------------------
// GetCStr
//----------------------------------------------------------------------
-const char *
-DNBDataRef::GetCStr(offset_t *offset_ptr, uint32_t fixed_length) const
-{
- const char *s = NULL;
- if ( m_start < m_end )
- {
- s = (char*)m_start + *offset_ptr;
-
- // Advance the offset
- if (fixed_length)
- *offset_ptr += fixed_length;
- else
- *offset_ptr += strlen(s) + 1;
- }
- return s;
+const char *DNBDataRef::GetCStr(offset_t *offset_ptr,
+ uint32_t fixed_length) const {
+ const char *s = NULL;
+ if (m_start < m_end) {
+ s = (char *)m_start + *offset_ptr;
+
+ // Advance the offset
+ if (fixed_length)
+ *offset_ptr += fixed_length;
+ else
+ *offset_ptr += strlen(s) + 1;
+ }
+ return s;
}
-
//----------------------------------------------------------------------
// GetData
//----------------------------------------------------------------------
-const uint8_t *
-DNBDataRef::GetData(offset_t *offset_ptr, uint32_t length) const
-{
- const uint8_t *data = NULL;
- if ( length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length) )
- {
- data = m_start + *offset_ptr;
- *offset_ptr += length;
- }
- return data;
+const uint8_t *DNBDataRef::GetData(offset_t *offset_ptr,
+ uint32_t length) const {
+ const uint8_t *data = NULL;
+ if (length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length)) {
+ data = m_start + *offset_ptr;
+ *offset_ptr += length;
+ }
+ return data;
}
-
//----------------------------------------------------------------------
// Get_ULEB128
//----------------------------------------------------------------------
-uint64_t
-DNBDataRef::Get_ULEB128 (offset_t *offset_ptr) const
-{
- uint64_t result = 0;
- if ( m_start < m_end )
- {
- int shift = 0;
- const uint8_t *src = m_start + *offset_ptr;
- uint8_t byte;
- int bytecount = 0;
-
- while (src < m_end)
- {
- bytecount++;
- byte = *src++;
- result |= (uint64_t)(byte & 0x7f) << shift;
- shift += 7;
- if ((byte & 0x80) == 0)
- break;
- }
-
- *offset_ptr += bytecount;
- }
- return result;
+uint64_t DNBDataRef::Get_ULEB128(offset_t *offset_ptr) const {
+ uint64_t result = 0;
+ if (m_start < m_end) {
+ int shift = 0;
+ const uint8_t *src = m_start + *offset_ptr;
+ uint8_t byte;
+ int bytecount = 0;
+
+ while (src < m_end) {
+ bytecount++;
+ byte = *src++;
+ result |= (uint64_t)(byte & 0x7f) << shift;
+ shift += 7;
+ if ((byte & 0x80) == 0)
+ break;
+ }
+
+ *offset_ptr += bytecount;
+ }
+ return result;
}
-
//----------------------------------------------------------------------
// Get_SLEB128
//----------------------------------------------------------------------
-int64_t
-DNBDataRef::Get_SLEB128 (offset_t *offset_ptr) const
-{
- int64_t result = 0;
-
- if ( m_start < m_end )
- {
- int shift = 0;
- int size = sizeof (uint32_t) * 8;
- const uint8_t *src = m_start + *offset_ptr;
-
- uint8_t byte = 0;
- int bytecount = 0;
-
- while (src < m_end)
- {
- bytecount++;
- byte = *src++;
- result |= (int64_t)(byte & 0x7f) << shift;
- shift += 7;
- if ((byte & 0x80) == 0)
- break;
- }
-
- // Sign bit of byte is 2nd high order bit (0x40)
- if (shift < size && (byte & 0x40))
- result |= - (1ll << shift);
+int64_t DNBDataRef::Get_SLEB128(offset_t *offset_ptr) const {
+ int64_t result = 0;
- *offset_ptr += bytecount;
- }
- return result;
+ if (m_start < m_end) {
+ int shift = 0;
+ int size = sizeof(uint32_t) * 8;
+ const uint8_t *src = m_start + *offset_ptr;
+
+ uint8_t byte = 0;
+ int bytecount = 0;
+
+ while (src < m_end) {
+ bytecount++;
+ byte = *src++;
+ result |= (int64_t)(byte & 0x7f) << shift;
+ shift += 7;
+ if ((byte & 0x80) == 0)
+ break;
+ }
+
+ // Sign bit of byte is 2nd high order bit (0x40)
+ if (shift < size && (byte & 0x40))
+ result |= -(1ll << shift);
+
+ *offset_ptr += bytecount;
+ }
+ return result;
}
-
//----------------------------------------------------------------------
// Skip_LEB128
//
// Skips past ULEB128 and SLEB128 numbers (just updates the offset)
//----------------------------------------------------------------------
-void
-DNBDataRef::Skip_LEB128 (offset_t *offset_ptr) const
-{
- if ( m_start < m_end )
- {
- const uint8_t *start = m_start + *offset_ptr;
- const uint8_t *src = start;
-
- while ((src < m_end) && (*src++ & 0x80))
- /* Do nothing */;
-
- *offset_ptr += src - start;
- }
-}
-
-uint32_t
-DNBDataRef::Dump
-(
- uint32_t startOffset,
- uint32_t endOffset,
- uint64_t offsetBase,
- DNBDataRef::Type type,
- uint32_t numPerLine,
- const char *format
-)
-{
- uint32_t offset;
- uint32_t count;
- char str[1024];
- str[0] = '\0';
- size_t str_offset = 0;
-
- for (offset = startOffset, count = 0; ValidOffset(offset) && offset < endOffset; ++count)
- {
- if ((count % numPerLine) == 0)
- {
- // Print out any previous string
- if (str[0] != '\0')
- DNBLog("%s", str);
- // Reset string offset and fill the current line string with address:
- str_offset = 0;
- str_offset += snprintf(str, sizeof(str), "0x%8.8llx:", (uint64_t)(offsetBase + (offset - startOffset)));
- }
-
- // Make sure we don't pass the bounds of our current string buffer on each iteration through this loop
- if (str_offset >= sizeof(str))
- {
- // The last snprintf consumed our string buffer, we will need to dump this out
- // and reset the string with no address
- DNBLog("%s", str);
- str_offset = 0;
- str[0] = '\0';
- }
-
- // We already checked that there is at least some room in the string str above, so it is safe to make
- // the snprintf call each time through this loop
- switch (type)
- {
- case TypeUInt8: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %2.2x", Get8(&offset)); break;
- case TypeChar:
- {
- char ch = Get8(&offset);
- str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %c", isprint(ch) ? ch : ' ');
- }
- break;
- case TypeUInt16: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %4.4x", Get16(&offset)); break;
- case TypeUInt32: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %8.8x", Get32(&offset)); break;
- case TypeUInt64: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %16.16llx", Get64(&offset)); break;
- case TypePointer: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " 0x%llx", GetPointer(&offset)); break;
- case TypeULEB128: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " 0x%llx", Get_ULEB128(&offset)); break;
- case TypeSLEB128: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %lld", Get_SLEB128(&offset)); break;
- }
+void DNBDataRef::Skip_LEB128(offset_t *offset_ptr) const {
+ if (m_start < m_end) {
+ const uint8_t *start = m_start + *offset_ptr;
+ const uint8_t *src = start;
+
+ while ((src < m_end) && (*src++ & 0x80))
+ /* Do nothing */;
+
+ *offset_ptr += src - start;
+ }
+}
+
+uint32_t DNBDataRef::Dump(uint32_t startOffset, uint32_t endOffset,
+ uint64_t offsetBase, DNBDataRef::Type type,
+ uint32_t numPerLine, const char *format) {
+ uint32_t offset;
+ uint32_t count;
+ char str[1024];
+ str[0] = '\0';
+ size_t str_offset = 0;
+
+ for (offset = startOffset, count = 0;
+ ValidOffset(offset) && offset < endOffset; ++count) {
+ if ((count % numPerLine) == 0) {
+ // Print out any previous string
+ if (str[0] != '\0')
+ DNBLog("%s", str);
+ // Reset string offset and fill the current line string with address:
+ str_offset = 0;
+ str_offset += snprintf(str, sizeof(str), "0x%8.8llx:",
+ (uint64_t)(offsetBase + (offset - startOffset)));
+ }
+
+ // Make sure we don't pass the bounds of our current string buffer on each
+ // iteration through this loop
+ if (str_offset >= sizeof(str)) {
+ // The last snprintf consumed our string buffer, we will need to dump this
+ // out
+ // and reset the string with no address
+ DNBLog("%s", str);
+ str_offset = 0;
+ str[0] = '\0';
+ }
+
+ // We already checked that there is at least some room in the string str
+ // above, so it is safe to make
+ // the snprintf call each time through this loop
+ switch (type) {
+ case TypeUInt8:
+ str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
+ format ? format : " %2.2x", Get8(&offset));
+ break;
+ case TypeChar: {
+ char ch = Get8(&offset);
+ str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
+ format ? format : " %c", isprint(ch) ? ch : ' ');
+ } break;
+ case TypeUInt16:
+ str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
+ format ? format : " %4.4x", Get16(&offset));
+ break;
+ case TypeUInt32:
+ str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
+ format ? format : " %8.8x", Get32(&offset));
+ break;
+ case TypeUInt64:
+ str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
+ format ? format : " %16.16llx", Get64(&offset));
+ break;
+ case TypePointer:
+ str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
+ format ? format : " 0x%llx", GetPointer(&offset));
+ break;
+ case TypeULEB128:
+ str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
+ format ? format : " 0x%llx", Get_ULEB128(&offset));
+ break;
+ case TypeSLEB128:
+ str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
+ format ? format : " %lld", Get_SLEB128(&offset));
+ break;
}
+ }
- if (str[0] != '\0')
- DNBLog("%s", str);
+ if (str[0] != '\0')
+ DNBLog("%s", str);
- return offset; // Return the offset at which we ended up
+ return offset; // Return the offset at which we ended up
}
Modified: lldb/trunk/tools/debugserver/source/DNBDataRef.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBDataRef.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBDataRef.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBDataRef.h Tue Sep 6 15:57:50 2016
@@ -24,102 +24,102 @@
#define __DNBDataRef_h__
#include "DNBDefs.h"
+#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
-#include <limits.h>
-class DNBDataRef
-{
+class DNBDataRef {
public:
- // For use with Dump
- typedef enum
- {
- TypeUInt8 = 0,
- TypeChar,
- TypeUInt16,
- TypeUInt32,
- TypeUInt64,
- TypePointer,
- TypeULEB128,
- TypeSLEB128
- } Type;
- typedef uint32_t offset_t;
- typedef nub_addr_t addr_t;
-
- DNBDataRef();
- DNBDataRef(const uint8_t *start, size_t size, bool swap);
- ~DNBDataRef();
- void Clear()
- {
- DNBDataRef::SetData(NULL, 0);
- m_swap = false;
- }
-
- size_t BytesLeft (size_t offset) const
- {
- const size_t size = GetSize();
- if (size > offset)
- return size - offset;
- return 0;
- }
-
- bool ValidOffset(offset_t offset) const
- {
- return BytesLeft(offset) > 0;
- }
- bool ValidOffsetForDataOfSize(offset_t offset, uint32_t num_bytes) const
- {
- return num_bytes <= BytesLeft (offset);
- }
- size_t GetSize() const { return m_end - m_start; }
- const uint8_t * GetDataStart() const { return m_start; }
- const uint8_t * GetDataEnd() const { return m_end; }
- bool GetSwap() const { return m_swap; }
- void SetSwap(bool swap) { m_swap = swap; }
- void SetData(const uint8_t *start, size_t size)
- {
- m_start = start;
- if (m_start != NULL)
- m_end = start + size;
- else
- m_end = NULL;
- }
- uint8_t GetPointerSize() const { return m_ptrSize; }
- void SetPointerSize(uint8_t size) { m_ptrSize = size; }
- void SetEHPtrBaseAddrPCRelative(addr_t addr = INVALID_NUB_ADDRESS) { m_addrPCRelative = addr; }
- void SetEHPtrBaseAddrTEXT(addr_t addr = INVALID_NUB_ADDRESS) { m_addrTEXT = addr; }
- void SetEHPtrBaseAddrDATA(addr_t addr = INVALID_NUB_ADDRESS) { m_addrDATA = addr; }
- uint8_t Get8(offset_t *offset_ptr) const;
- uint16_t Get16(offset_t *offset_ptr) const;
- uint32_t Get32(offset_t *offset_ptr) const;
- uint64_t Get64(offset_t *offset_ptr) const;
- uint32_t GetMax32(offset_t *offset_ptr, uint32_t byte_size) const;
- uint64_t GetMax64(offset_t *offset_ptr, uint32_t byte_size) const;
- uint64_t GetPointer(offset_t *offset_ptr) const;
-// uint64_t GetDwarfEHPtr(offset_t *offset_ptr, uint32_t eh_ptr_enc) const;
- const char * GetCStr(offset_t *offset_ptr, uint32_t fixed_length = 0) const;
- const char * PeekCStr(offset_t offset) const
- {
- if (ValidOffset(offset))
- return (const char*)m_start + offset;
- return NULL;
- }
-
- const uint8_t * GetData( offset_t *offset_ptr, uint32_t length) const;
- uint64_t Get_ULEB128 (offset_t *offset_ptr) const;
- int64_t Get_SLEB128 (offset_t *offset_ptr) const;
- void Skip_LEB128 (offset_t *offset_ptr) const;
+ // For use with Dump
+ typedef enum {
+ TypeUInt8 = 0,
+ TypeChar,
+ TypeUInt16,
+ TypeUInt32,
+ TypeUInt64,
+ TypePointer,
+ TypeULEB128,
+ TypeSLEB128
+ } Type;
+ typedef uint32_t offset_t;
+ typedef nub_addr_t addr_t;
+
+ DNBDataRef();
+ DNBDataRef(const uint8_t *start, size_t size, bool swap);
+ ~DNBDataRef();
+ void Clear() {
+ DNBDataRef::SetData(NULL, 0);
+ m_swap = false;
+ }
+
+ size_t BytesLeft(size_t offset) const {
+ const size_t size = GetSize();
+ if (size > offset)
+ return size - offset;
+ return 0;
+ }
+
+ bool ValidOffset(offset_t offset) const { return BytesLeft(offset) > 0; }
+ bool ValidOffsetForDataOfSize(offset_t offset, uint32_t num_bytes) const {
+ return num_bytes <= BytesLeft(offset);
+ }
+ size_t GetSize() const { return m_end - m_start; }
+ const uint8_t *GetDataStart() const { return m_start; }
+ const uint8_t *GetDataEnd() const { return m_end; }
+ bool GetSwap() const { return m_swap; }
+ void SetSwap(bool swap) { m_swap = swap; }
+ void SetData(const uint8_t *start, size_t size) {
+ m_start = start;
+ if (m_start != NULL)
+ m_end = start + size;
+ else
+ m_end = NULL;
+ }
+ uint8_t GetPointerSize() const { return m_ptrSize; }
+ void SetPointerSize(uint8_t size) { m_ptrSize = size; }
+ void SetEHPtrBaseAddrPCRelative(addr_t addr = INVALID_NUB_ADDRESS) {
+ m_addrPCRelative = addr;
+ }
+ void SetEHPtrBaseAddrTEXT(addr_t addr = INVALID_NUB_ADDRESS) {
+ m_addrTEXT = addr;
+ }
+ void SetEHPtrBaseAddrDATA(addr_t addr = INVALID_NUB_ADDRESS) {
+ m_addrDATA = addr;
+ }
+ uint8_t Get8(offset_t *offset_ptr) const;
+ uint16_t Get16(offset_t *offset_ptr) const;
+ uint32_t Get32(offset_t *offset_ptr) const;
+ uint64_t Get64(offset_t *offset_ptr) const;
+ uint32_t GetMax32(offset_t *offset_ptr, uint32_t byte_size) const;
+ uint64_t GetMax64(offset_t *offset_ptr, uint32_t byte_size) const;
+ uint64_t GetPointer(offset_t *offset_ptr) const;
+ // uint64_t GetDwarfEHPtr(offset_t *offset_ptr, uint32_t eh_ptr_enc)
+ // const;
+ const char *GetCStr(offset_t *offset_ptr, uint32_t fixed_length = 0) const;
+ const char *PeekCStr(offset_t offset) const {
+ if (ValidOffset(offset))
+ return (const char *)m_start + offset;
+ return NULL;
+ }
+
+ const uint8_t *GetData(offset_t *offset_ptr, uint32_t length) const;
+ uint64_t Get_ULEB128(offset_t *offset_ptr) const;
+ int64_t Get_SLEB128(offset_t *offset_ptr) const;
+ void Skip_LEB128(offset_t *offset_ptr) const;
+
+ uint32_t Dump(offset_t startOffset, offset_t endOffset, uint64_t offsetBase,
+ DNBDataRef::Type type, uint32_t numPerLine,
+ const char *typeFormat = NULL);
- uint32_t Dump(offset_t startOffset, offset_t endOffset, uint64_t offsetBase, DNBDataRef::Type type, uint32_t numPerLine, const char *typeFormat = NULL);
protected:
- const uint8_t * m_start;
- const uint8_t * m_end;
- bool m_swap;
- uint8_t m_ptrSize;
- addr_t m_addrPCRelative;
- addr_t m_addrTEXT;
- addr_t m_addrDATA;
+ const uint8_t *m_start;
+ const uint8_t *m_end;
+ bool m_swap;
+ uint8_t m_ptrSize;
+ addr_t m_addrPCRelative;
+ addr_t m_addrTEXT;
+ addr_t m_addrDATA;
};
#endif // #ifndef __DNBDataRef_h__
Modified: lldb/trunk/tools/debugserver/source/DNBDefs.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBDefs.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBDefs.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBDefs.h Tue Sep 6 15:57:50 2016
@@ -14,8 +14,8 @@
#ifndef __DNBDefs_h__
#define __DNBDefs_h__
-#include <stdint.h>
#include <signal.h>
+#include <stdint.h>
#include <stdio.h>
#include <sys/syslimits.h>
#include <unistd.h>
@@ -23,22 +23,24 @@
//----------------------------------------------------------------------
// Define nub_addr_t and the invalid address value from the architecture
//----------------------------------------------------------------------
-#if defined (__x86_64__) || defined (__ppc64__) || defined (__arm64__) || defined (__aarch64__)
+#if defined(__x86_64__) || defined(__ppc64__) || defined(__arm64__) || \
+ defined(__aarch64__)
//----------------------------------------------------------------------
// 64 bit address architectures
//----------------------------------------------------------------------
-typedef uint64_t nub_addr_t;
-#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ull)
+typedef uint64_t nub_addr_t;
+#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ull)
-#elif defined (__i386__) || defined (__powerpc__) || defined (__ppc__) || defined (__arm__)
+#elif defined(__i386__) || defined(__powerpc__) || defined(__ppc__) || \
+ defined(__arm__)
//----------------------------------------------------------------------
// 32 bit address architectures
//----------------------------------------------------------------------
-typedef uint32_t nub_addr_t;
-#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ul)
+typedef uint32_t nub_addr_t;
+#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ul)
#else
@@ -47,327 +49,325 @@ typedef uint32_t nub_addr_t;
//----------------------------------------------------------------------
#warning undefined architecture, defaulting to 8 byte addresses
-typedef uint64_t nub_addr_t;
-#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ull)
-
+typedef uint64_t nub_addr_t;
+#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ull)
#endif
-typedef size_t nub_size_t;
-typedef ssize_t nub_ssize_t;
-typedef uint32_t nub_index_t;
-typedef pid_t nub_process_t;
-typedef uint64_t nub_thread_t;
-typedef uint32_t nub_event_t;
-typedef uint32_t nub_bool_t;
-
-#define INVALID_NUB_PROCESS ((nub_process_t)0)
-#define INVALID_NUB_THREAD ((nub_thread_t)0)
-#define INVALID_NUB_WATCH_ID ((nub_watch_t)0)
-#define INVALID_NUB_HW_INDEX UINT32_MAX
-#define INVALID_NUB_REGNUM UINT32_MAX
-#define NUB_GENERIC_ERROR UINT32_MAX
+typedef size_t nub_size_t;
+typedef ssize_t nub_ssize_t;
+typedef uint32_t nub_index_t;
+typedef pid_t nub_process_t;
+typedef uint64_t nub_thread_t;
+typedef uint32_t nub_event_t;
+typedef uint32_t nub_bool_t;
+
+#define INVALID_NUB_PROCESS ((nub_process_t)0)
+#define INVALID_NUB_THREAD ((nub_thread_t)0)
+#define INVALID_NUB_WATCH_ID ((nub_watch_t)0)
+#define INVALID_NUB_HW_INDEX UINT32_MAX
+#define INVALID_NUB_REGNUM UINT32_MAX
+#define NUB_GENERIC_ERROR UINT32_MAX
// Watchpoint types
-#define WATCH_TYPE_READ (1u << 0)
-#define WATCH_TYPE_WRITE (1u << 1)
+#define WATCH_TYPE_READ (1u << 0)
+#define WATCH_TYPE_WRITE (1u << 1)
-typedef enum
-{
- eStateInvalid = 0,
- eStateUnloaded,
- eStateAttaching,
- eStateLaunching,
- eStateStopped,
- eStateRunning,
- eStateStepping,
- eStateCrashed,
- eStateDetached,
- eStateExited,
- eStateSuspended
+typedef enum {
+ eStateInvalid = 0,
+ eStateUnloaded,
+ eStateAttaching,
+ eStateLaunching,
+ eStateStopped,
+ eStateRunning,
+ eStateStepping,
+ eStateCrashed,
+ eStateDetached,
+ eStateExited,
+ eStateSuspended
} nub_state_t;
-typedef enum
-{
- eLaunchFlavorDefault = 0,
- eLaunchFlavorPosixSpawn = 1,
- eLaunchFlavorForkExec = 2,
+typedef enum {
+ eLaunchFlavorDefault = 0,
+ eLaunchFlavorPosixSpawn = 1,
+ eLaunchFlavorForkExec = 2,
#ifdef WITH_SPRINGBOARD
- eLaunchFlavorSpringBoard = 3,
+ eLaunchFlavorSpringBoard = 3,
#endif
#ifdef WITH_BKS
- eLaunchFlavorBKS = 4,
+ eLaunchFlavorBKS = 4,
#endif
#ifdef WITH_FBS
- eLaunchFlavorFBS = 5
+ eLaunchFlavorFBS = 5
#endif
} nub_launch_flavor_t;
-#define NUB_STATE_IS_RUNNING(s) ((s) == eStateAttaching ||\
- (s) == eStateLaunching ||\
- (s) == eStateRunning ||\
- (s) == eStateStepping ||\
- (s) == eStateDetached)
-
-#define NUB_STATE_IS_STOPPED(s) ((s) == eStateUnloaded ||\
- (s) == eStateStopped ||\
- (s) == eStateCrashed ||\
- (s) == eStateExited)
-
-enum
-{
- eEventProcessRunningStateChanged = 1 << 0, // The process has changed state to running
- eEventProcessStoppedStateChanged = 1 << 1, // The process has changed state to stopped
- eEventSharedLibsStateChange = 1 << 2, // Shared libraries loaded/unloaded state has changed
- eEventStdioAvailable = 1 << 3, // Something is available on stdout/stderr
- eEventProfileDataAvailable = 1 << 4, // Profile data ready for retrieval
- kAllEventsMask = eEventProcessRunningStateChanged |
- eEventProcessStoppedStateChanged |
- eEventSharedLibsStateChange |
- eEventStdioAvailable |
- eEventProfileDataAvailable
-};
-
-#define LOG_VERBOSE (1u << 0)
-#define LOG_PROCESS (1u << 1)
-#define LOG_THREAD (1u << 2)
-#define LOG_EXCEPTIONS (1u << 3)
-#define LOG_SHLIB (1u << 4)
-#define LOG_MEMORY (1u << 5) // Log memory reads/writes calls
-#define LOG_MEMORY_DATA_SHORT (1u << 6) // Log short memory reads/writes bytes
-#define LOG_MEMORY_DATA_LONG (1u << 7) // Log all memory reads/writes bytes
-#define LOG_MEMORY_PROTECTIONS (1u << 8) // Log memory protection changes
-#define LOG_BREAKPOINTS (1u << 9)
-#define LOG_EVENTS (1u << 10)
-#define LOG_WATCHPOINTS (1u << 11)
-#define LOG_STEP (1u << 12)
-#define LOG_TASK (1u << 13)
-#define LOG_DARWIN_LOG (1u << 14)
-#define LOG_LO_USER (1u << 16)
-#define LOG_HI_USER (1u << 31)
-#define LOG_ALL 0xFFFFFFFFu
-#define LOG_DEFAULT ((LOG_PROCESS) |\
- (LOG_TASK) |\
- (LOG_THREAD) |\
- (LOG_EXCEPTIONS) |\
- (LOG_SHLIB) |\
- (LOG_MEMORY) |\
- (LOG_BREAKPOINTS) |\
- (LOG_WATCHPOINTS) |\
- (LOG_STEP))
+#define NUB_STATE_IS_RUNNING(s) \
+ ((s) == eStateAttaching || (s) == eStateLaunching || (s) == eStateRunning || \
+ (s) == eStateStepping || (s) == eStateDetached)
+
+#define NUB_STATE_IS_STOPPED(s) \
+ ((s) == eStateUnloaded || (s) == eStateStopped || (s) == eStateCrashed || \
+ (s) == eStateExited)
+
+enum {
+ eEventProcessRunningStateChanged =
+ 1 << 0, // The process has changed state to running
+ eEventProcessStoppedStateChanged =
+ 1 << 1, // The process has changed state to stopped
+ eEventSharedLibsStateChange =
+ 1 << 2, // Shared libraries loaded/unloaded state has changed
+ eEventStdioAvailable = 1 << 3, // Something is available on stdout/stderr
+ eEventProfileDataAvailable = 1 << 4, // Profile data ready for retrieval
+ kAllEventsMask = eEventProcessRunningStateChanged |
+ eEventProcessStoppedStateChanged |
+ eEventSharedLibsStateChange | eEventStdioAvailable |
+ eEventProfileDataAvailable
+};
+
+#define LOG_VERBOSE (1u << 0)
+#define LOG_PROCESS (1u << 1)
+#define LOG_THREAD (1u << 2)
+#define LOG_EXCEPTIONS (1u << 3)
+#define LOG_SHLIB (1u << 4)
+#define LOG_MEMORY (1u << 5) // Log memory reads/writes calls
+#define LOG_MEMORY_DATA_SHORT (1u << 6) // Log short memory reads/writes bytes
+#define LOG_MEMORY_DATA_LONG (1u << 7) // Log all memory reads/writes bytes
+#define LOG_MEMORY_PROTECTIONS (1u << 8) // Log memory protection changes
+#define LOG_BREAKPOINTS (1u << 9)
+#define LOG_EVENTS (1u << 10)
+#define LOG_WATCHPOINTS (1u << 11)
+#define LOG_STEP (1u << 12)
+#define LOG_TASK (1u << 13)
+#define LOG_DARWIN_LOG (1u << 14)
+#define LOG_LO_USER (1u << 16)
+#define LOG_HI_USER (1u << 31)
+#define LOG_ALL 0xFFFFFFFFu
+#define LOG_DEFAULT \
+ ((LOG_PROCESS) | (LOG_TASK) | (LOG_THREAD) | (LOG_EXCEPTIONS) | \
+ (LOG_SHLIB) | (LOG_MEMORY) | (LOG_BREAKPOINTS) | (LOG_WATCHPOINTS) | \
+ (LOG_STEP))
-
-#define REGISTER_SET_ALL 0
+#define REGISTER_SET_ALL 0
// Generic Register set to be defined by each architecture for access to common
// register values.
-#define REGISTER_SET_GENERIC ((uint32_t)0xFFFFFFFFu)
-#define GENERIC_REGNUM_PC 0 // Program Counter
-#define GENERIC_REGNUM_SP 1 // Stack Pointer
-#define GENERIC_REGNUM_FP 2 // Frame Pointer
-#define GENERIC_REGNUM_RA 3 // Return Address
-#define GENERIC_REGNUM_FLAGS 4 // Processor flags register
-#define GENERIC_REGNUM_ARG1 5 // The register that would contain pointer size or less argument 1 (if any)
-#define GENERIC_REGNUM_ARG2 6 // The register that would contain pointer size or less argument 2 (if any)
-#define GENERIC_REGNUM_ARG3 7 // The register that would contain pointer size or less argument 3 (if any)
-#define GENERIC_REGNUM_ARG4 8 // The register that would contain pointer size or less argument 4 (if any)
-#define GENERIC_REGNUM_ARG5 9 // The register that would contain pointer size or less argument 5 (if any)
-#define GENERIC_REGNUM_ARG6 10 // The register that would contain pointer size or less argument 6 (if any)
-#define GENERIC_REGNUM_ARG7 11 // The register that would contain pointer size or less argument 7 (if any)
-#define GENERIC_REGNUM_ARG8 12 // The register that would contain pointer size or less argument 8 (if any)
-
-enum DNBRegisterType
-{
- InvalidRegType = 0,
- Uint, // unsigned integer
- Sint, // signed integer
- IEEE754, // float
- Vector // vector registers
-};
-
-enum DNBRegisterFormat
-{
- InvalidRegFormat = 0,
- Binary,
- Decimal,
- Hex,
- Float,
- VectorOfSInt8,
- VectorOfUInt8,
- VectorOfSInt16,
- VectorOfUInt16,
- VectorOfSInt32,
- VectorOfUInt32,
- VectorOfFloat32,
- VectorOfUInt128
-};
-
-struct DNBRegisterInfo
-{
- uint32_t set; // Register set
- uint32_t reg; // Register number
- const char *name; // Name of this register
- const char *alt; // Alternate name
- uint16_t type; // Type of the register bits (DNBRegisterType)
- uint16_t format; // Default format for display (DNBRegisterFormat),
- uint32_t size; // Size in bytes of the register
- uint32_t offset; // Offset from the beginning of the register context
- uint32_t reg_ehframe; // eh_frame register number (INVALID_NUB_REGNUM when none)
- uint32_t reg_dwarf; // DWARF register number (INVALID_NUB_REGNUM when none)
- uint32_t reg_generic; // Generic register number (INVALID_NUB_REGNUM when none)
- uint32_t reg_debugserver;// The debugserver register number we'll use over gdb-remote protocol (INVALID_NUB_REGNUM when none)
- const char **value_regs; // If this register is a part of other registers, list the register names terminated by NULL
- const char **update_regs; // If modifying this register will invalidate other registers, list the register names terminated by NULL
-};
-
-struct DNBRegisterSetInfo
-{
- const char *name; // Name of this register set
- const struct DNBRegisterInfo *registers; // An array of register descriptions
- nub_size_t num_registers; // The number of registers in REGISTERS array above
-};
-
-struct DNBThreadResumeAction
-{
- nub_thread_t tid; // The thread ID that this action applies to, INVALID_NUB_THREAD for the default thread action
- nub_state_t state; // Valid values are eStateStopped/eStateSuspended, eStateRunning, and eStateStepping.
- int signal; // When resuming this thread, resume it with this signal
- nub_addr_t addr; // If not INVALID_NUB_ADDRESS, then set the PC for the thread to ADDR before resuming/stepping
-};
-
-enum DNBThreadStopType
-{
- eStopTypeInvalid = 0,
- eStopTypeSignal,
- eStopTypeException,
- eStopTypeExec
-};
-
-enum DNBMemoryPermissions
-{
- eMemoryPermissionsWritable = (1 << 0),
- eMemoryPermissionsReadable = (1 << 1),
- eMemoryPermissionsExecutable = (1 << 2)
+#define REGISTER_SET_GENERIC ((uint32_t)0xFFFFFFFFu)
+#define GENERIC_REGNUM_PC 0 // Program Counter
+#define GENERIC_REGNUM_SP 1 // Stack Pointer
+#define GENERIC_REGNUM_FP 2 // Frame Pointer
+#define GENERIC_REGNUM_RA 3 // Return Address
+#define GENERIC_REGNUM_FLAGS 4 // Processor flags register
+#define GENERIC_REGNUM_ARG1 \
+ 5 // The register that would contain pointer size or less argument 1 (if any)
+#define GENERIC_REGNUM_ARG2 \
+ 6 // The register that would contain pointer size or less argument 2 (if any)
+#define GENERIC_REGNUM_ARG3 \
+ 7 // The register that would contain pointer size or less argument 3 (if any)
+#define GENERIC_REGNUM_ARG4 \
+ 8 // The register that would contain pointer size or less argument 4 (if any)
+#define GENERIC_REGNUM_ARG5 \
+ 9 // The register that would contain pointer size or less argument 5 (if any)
+#define GENERIC_REGNUM_ARG6 \
+ 10 // The register that would contain pointer size or less argument 6 (if any)
+#define GENERIC_REGNUM_ARG7 \
+ 11 // The register that would contain pointer size or less argument 7 (if any)
+#define GENERIC_REGNUM_ARG8 \
+ 12 // The register that would contain pointer size or less argument 8 (if any)
+
+enum DNBRegisterType {
+ InvalidRegType = 0,
+ Uint, // unsigned integer
+ Sint, // signed integer
+ IEEE754, // float
+ Vector // vector registers
+};
+
+enum DNBRegisterFormat {
+ InvalidRegFormat = 0,
+ Binary,
+ Decimal,
+ Hex,
+ Float,
+ VectorOfSInt8,
+ VectorOfUInt8,
+ VectorOfSInt16,
+ VectorOfUInt16,
+ VectorOfSInt32,
+ VectorOfUInt32,
+ VectorOfFloat32,
+ VectorOfUInt128
+};
+
+struct DNBRegisterInfo {
+ uint32_t set; // Register set
+ uint32_t reg; // Register number
+ const char *name; // Name of this register
+ const char *alt; // Alternate name
+ uint16_t type; // Type of the register bits (DNBRegisterType)
+ uint16_t format; // Default format for display (DNBRegisterFormat),
+ uint32_t size; // Size in bytes of the register
+ uint32_t offset; // Offset from the beginning of the register context
+ uint32_t
+ reg_ehframe; // eh_frame register number (INVALID_NUB_REGNUM when none)
+ uint32_t reg_dwarf; // DWARF register number (INVALID_NUB_REGNUM when none)
+ uint32_t
+ reg_generic; // Generic register number (INVALID_NUB_REGNUM when none)
+ uint32_t reg_debugserver; // The debugserver register number we'll use over
+ // gdb-remote protocol (INVALID_NUB_REGNUM when
+ // none)
+ const char **value_regs; // If this register is a part of other registers,
+ // list the register names terminated by NULL
+ const char **update_regs; // If modifying this register will invalidate other
+ // registers, list the register names terminated by
+ // NULL
+};
+
+struct DNBRegisterSetInfo {
+ const char *name; // Name of this register set
+ const struct DNBRegisterInfo *registers; // An array of register descriptions
+ nub_size_t num_registers; // The number of registers in REGISTERS array above
+};
+
+struct DNBThreadResumeAction {
+ nub_thread_t tid; // The thread ID that this action applies to,
+ // INVALID_NUB_THREAD for the default thread action
+ nub_state_t state; // Valid values are eStateStopped/eStateSuspended,
+ // eStateRunning, and eStateStepping.
+ int signal; // When resuming this thread, resume it with this signal
+ nub_addr_t addr; // If not INVALID_NUB_ADDRESS, then set the PC for the thread
+ // to ADDR before resuming/stepping
+};
+
+enum DNBThreadStopType {
+ eStopTypeInvalid = 0,
+ eStopTypeSignal,
+ eStopTypeException,
+ eStopTypeExec
+};
+
+enum DNBMemoryPermissions {
+ eMemoryPermissionsWritable = (1 << 0),
+ eMemoryPermissionsReadable = (1 << 1),
+ eMemoryPermissionsExecutable = (1 << 2)
};
-#define DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH 256
-#define DNB_THREAD_STOP_INFO_MAX_EXC_DATA 8
+#define DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH 256
+#define DNB_THREAD_STOP_INFO_MAX_EXC_DATA 8
//----------------------------------------------------------------------
// DNBThreadStopInfo
//
// Describes the reason a thread stopped.
//----------------------------------------------------------------------
-struct DNBThreadStopInfo
-{
- DNBThreadStopType reason;
- char description[DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH];
- union
- {
- // eStopTypeSignal
- struct
- {
- uint32_t signo;
- } signal;
-
- // eStopTypeException
- struct
- {
- uint32_t type;
- nub_size_t data_count;
- nub_addr_t data[DNB_THREAD_STOP_INFO_MAX_EXC_DATA];
- } exception;
- } details;
+struct DNBThreadStopInfo {
+ DNBThreadStopType reason;
+ char description[DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH];
+ union {
+ // eStopTypeSignal
+ struct {
+ uint32_t signo;
+ } signal;
+
+ // eStopTypeException
+ struct {
+ uint32_t type;
+ nub_size_t data_count;
+ nub_addr_t data[DNB_THREAD_STOP_INFO_MAX_EXC_DATA];
+ } exception;
+ } details;
+};
+
+struct DNBRegisterValue {
+ struct DNBRegisterInfo info; // Register information for this register
+ union {
+ int8_t sint8;
+ int16_t sint16;
+ int32_t sint32;
+ int64_t sint64;
+ uint8_t uint8;
+ uint16_t uint16;
+ uint32_t uint32;
+ uint64_t uint64;
+ float float32;
+ double float64;
+ int8_t v_sint8[32];
+ int16_t v_sint16[16];
+ int32_t v_sint32[8];
+ int64_t v_sint64[4];
+ uint8_t v_uint8[32];
+ uint16_t v_uint16[16];
+ uint32_t v_uint32[8];
+ uint64_t v_uint64[4];
+ float v_float32[8];
+ double v_float64[4];
+ void *pointer;
+ char *c_str;
+ } value;
};
-
-struct DNBRegisterValue
-{
- struct DNBRegisterInfo info; // Register information for this register
- union
- {
- int8_t sint8;
- int16_t sint16;
- int32_t sint32;
- int64_t sint64;
- uint8_t uint8;
- uint16_t uint16;
- uint32_t uint32;
- uint64_t uint64;
- float float32;
- double float64;
- int8_t v_sint8[32];
- int16_t v_sint16[16];
- int32_t v_sint32[8];
- int64_t v_sint64[4];
- uint8_t v_uint8[32];
- uint16_t v_uint16[16];
- uint32_t v_uint32[8];
- uint64_t v_uint64[4];
- float v_float32[8];
- double v_float64[4];
- void *pointer;
- char *c_str;
- } value;
-};
-
-enum DNBSharedLibraryState
-{
- eShlibStateUnloaded = 0,
- eShlibStateLoaded = 1
-};
+enum DNBSharedLibraryState { eShlibStateUnloaded = 0, eShlibStateLoaded = 1 };
#ifndef DNB_MAX_SEGMENT_NAME_LENGTH
-#define DNB_MAX_SEGMENT_NAME_LENGTH 32
+#define DNB_MAX_SEGMENT_NAME_LENGTH 32
#endif
-struct DNBSegment
-{
- char name[DNB_MAX_SEGMENT_NAME_LENGTH];
- nub_addr_t addr;
- nub_addr_t size;
-};
-
-struct DNBExecutableImageInfo
-{
- char name[PATH_MAX]; // Name of the executable image (usually a full path)
- uint32_t state; // State of the executable image (see enum DNBSharedLibraryState)
- nub_addr_t header_addr; // Executable header address
- uuid_t uuid; // Unique identifier for matching with symbols
- uint32_t num_segments; // Number of contiguous memory segments to in SEGMENTS array
- DNBSegment *segments; // Array of contiguous memory segments in executable
-};
-
-struct DNBRegionInfo
-{
- nub_addr_t addr;
- nub_addr_t size;
- uint32_t permissions;
-};
-
-enum DNBProfileDataScanType
-{
- eProfileHostCPU = (1 << 0),
- eProfileCPU = (1 << 1),
-
- eProfileThreadsCPU = (1 << 2), // By default excludes eProfileThreadName and eProfileQueueName.
- eProfileThreadName = (1 << 3), // Assume eProfileThreadsCPU, get thread name as well.
- eProfileQueueName = (1 << 4), // Assume eProfileThreadsCPU, get queue name as well.
-
- eProfileHostMemory = (1 << 5),
-
- eProfileMemory = (1 << 6), // By default, excludes eProfileMemoryDirtyPage.
- eProfileMemoryDirtyPage = (1 << 7), // Assume eProfileMemory, get Dirty Page size as well.
- eProfileMemoryAnonymous = (1 << 8), // Assume eProfileMemory, get Anonymous memory as well.
-
- eProfileEnergy = (1 << 9),
-
- eProfileAll = 0xffffffff
-};
-
-typedef nub_addr_t (*DNBCallbackNameToAddress)(nub_process_t pid, const char *name, const char *shlib_regex, void *baton);
-typedef nub_size_t (*DNBCallbackCopyExecutableImageInfos)(nub_process_t pid, struct DNBExecutableImageInfo **image_infos, nub_bool_t only_changed, void *baton);
-typedef void (*DNBCallbackLog)(void *baton, uint32_t flags, const char *format, va_list args);
+struct DNBSegment {
+ char name[DNB_MAX_SEGMENT_NAME_LENGTH];
+ nub_addr_t addr;
+ nub_addr_t size;
+};
+
+struct DNBExecutableImageInfo {
+ char name[PATH_MAX]; // Name of the executable image (usually a full path)
+ uint32_t
+ state; // State of the executable image (see enum DNBSharedLibraryState)
+ nub_addr_t header_addr; // Executable header address
+ uuid_t uuid; // Unique identifier for matching with symbols
+ uint32_t
+ num_segments; // Number of contiguous memory segments to in SEGMENTS array
+ DNBSegment *segments; // Array of contiguous memory segments in executable
+};
+
+struct DNBRegionInfo {
+ nub_addr_t addr;
+ nub_addr_t size;
+ uint32_t permissions;
+};
+
+enum DNBProfileDataScanType {
+ eProfileHostCPU = (1 << 0),
+ eProfileCPU = (1 << 1),
+
+ eProfileThreadsCPU =
+ (1 << 2), // By default excludes eProfileThreadName and eProfileQueueName.
+ eProfileThreadName =
+ (1 << 3), // Assume eProfileThreadsCPU, get thread name as well.
+ eProfileQueueName =
+ (1 << 4), // Assume eProfileThreadsCPU, get queue name as well.
+
+ eProfileHostMemory = (1 << 5),
+
+ eProfileMemory = (1 << 6), // By default, excludes eProfileMemoryDirtyPage.
+ eProfileMemoryDirtyPage =
+ (1 << 7), // Assume eProfileMemory, get Dirty Page size as well.
+ eProfileMemoryAnonymous =
+ (1 << 8), // Assume eProfileMemory, get Anonymous memory as well.
+
+ eProfileEnergy = (1 << 9),
+
+ eProfileAll = 0xffffffff
+};
+
+typedef nub_addr_t (*DNBCallbackNameToAddress)(nub_process_t pid,
+ const char *name,
+ const char *shlib_regex,
+ void *baton);
+typedef nub_size_t (*DNBCallbackCopyExecutableImageInfos)(
+ nub_process_t pid, struct DNBExecutableImageInfo **image_infos,
+ nub_bool_t only_changed, void *baton);
+typedef void (*DNBCallbackLog)(void *baton, uint32_t flags, const char *format,
+ va_list args);
#define UNUSED_IF_ASSERT_DISABLED(x) ((void)(x))
-#endif // #ifndef __DNBDefs_h__
+#endif // #ifndef __DNBDefs_h__
Modified: lldb/trunk/tools/debugserver/source/DNBError.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBError.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBError.cpp (original)
+++ lldb/trunk/tools/debugserver/source/DNBError.cpp Tue Sep 6 15:57:50 2016
@@ -20,109 +20,97 @@
#include <SpringBoardServices/SpringBoardServer.h>
#endif
-const char *
-DNBError::AsString() const
-{
- if (Success())
- return NULL;
-
- if (m_str.empty())
- {
- const char *s = NULL;
- switch (m_flavor)
- {
- case MachKernel:
- s = ::mach_error_string (m_err);
- break;
-
- case POSIX:
- s = ::strerror (m_err);
- break;
+const char *DNBError::AsString() const {
+ if (Success())
+ return NULL;
+
+ if (m_str.empty()) {
+ const char *s = NULL;
+ switch (m_flavor) {
+ case MachKernel:
+ s = ::mach_error_string(m_err);
+ break;
+
+ case POSIX:
+ s = ::strerror(m_err);
+ break;
#ifdef WITH_SPRINGBOARD
- case SpringBoard:
- {
- CFStringRef statusStr = SBSApplicationLaunchingErrorString (m_err);
- if (CFString::UTF8 (statusStr, m_str) == NULL)
- m_str.clear();
- }
- break;
+ case SpringBoard: {
+ CFStringRef statusStr = SBSApplicationLaunchingErrorString(m_err);
+ if (CFString::UTF8(statusStr, m_str) == NULL)
+ m_str.clear();
+ } break;
#endif
#ifdef WITH_BKS
- case BackBoard:
- {
- // You have to call ObjC routines to get the error string from BackBoardServices.
- // Not sure I want to make DNBError.cpp an .mm file. For now just make sure you
- // pre-populate the error string when you make the DNBError of type BackBoard.
- m_str.assign("Should have set BackBoard error when making the error string.");
- }
- break;
+ case BackBoard: {
+ // You have to call ObjC routines to get the error string from
+ // BackBoardServices.
+ // Not sure I want to make DNBError.cpp an .mm file. For now just make
+ // sure you
+ // pre-populate the error string when you make the DNBError of type
+ // BackBoard.
+ m_str.assign(
+ "Should have set BackBoard error when making the error string.");
+ } break;
#endif
#ifdef WITH_FBS
- case FrontBoard:
- {
- // You have to call ObjC routines to get the error string from FrontBoardServices.
- // Not sure I want to make DNBError.cpp an .mm file. For now just make sure you
- // pre-populate the error string when you make the DNBError of type FrontBoard.
- m_str.assign("Should have set FrontBoard error when making the error string.");
- }
- break;
+ case FrontBoard: {
+ // You have to call ObjC routines to get the error string from
+ // FrontBoardServices.
+ // Not sure I want to make DNBError.cpp an .mm file. For now just make
+ // sure you
+ // pre-populate the error string when you make the DNBError of type
+ // FrontBoard.
+ m_str.assign(
+ "Should have set FrontBoard error when making the error string.");
+ } break;
#endif
- default:
- break;
- }
- if (s)
- m_str.assign(s);
+ default:
+ break;
}
- if (m_str.empty())
- return NULL;
- return m_str.c_str();
+ if (s)
+ m_str.assign(s);
+ }
+ if (m_str.empty())
+ return NULL;
+ return m_str.c_str();
}
-void
-DNBError::LogThreadedIfError(const char *format, ...) const
-{
- if (Fail())
- {
- char *arg_msg = NULL;
- va_list args;
- va_start (args, format);
- ::vasprintf (&arg_msg, format, args);
- va_end (args);
-
- if (arg_msg != NULL)
- {
- const char *err_str = AsString();
- if (err_str == NULL)
- err_str = "???";
- DNBLogThreaded ("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_err);
- free (arg_msg);
- }
+void DNBError::LogThreadedIfError(const char *format, ...) const {
+ if (Fail()) {
+ char *arg_msg = NULL;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != NULL) {
+ const char *err_str = AsString();
+ if (err_str == NULL)
+ err_str = "???";
+ DNBLogThreaded("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_err);
+ free(arg_msg);
}
+ }
}
-void
-DNBError::LogThreaded(const char *format, ...) const
-{
- char *arg_msg = NULL;
- va_list args;
- va_start (args, format);
- ::vasprintf (&arg_msg, format, args);
- va_end (args);
-
- if (arg_msg != NULL)
- {
- if (Fail())
- {
- const char *err_str = AsString();
- if (err_str == NULL)
- err_str = "???";
- DNBLogThreaded ("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_err);
- }
- else
- {
- DNBLogThreaded ("%s err = 0x%8.8x", arg_msg, m_err);
- }
- free (arg_msg);
+void DNBError::LogThreaded(const char *format, ...) const {
+ char *arg_msg = NULL;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != NULL) {
+ if (Fail()) {
+ const char *err_str = AsString();
+ if (err_str == NULL)
+ err_str = "???";
+ DNBLogThreaded("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_err);
+ } else {
+ DNBLogThreaded("%s err = 0x%8.8x", arg_msg, m_err);
}
+ free(arg_msg);
+ }
}
Modified: lldb/trunk/tools/debugserver/source/DNBError.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBError.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBError.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBError.h Tue Sep 6 15:57:50 2016
@@ -19,84 +19,80 @@
#include <stdio.h>
#include <string>
-class DNBError
-{
+class DNBError {
public:
- typedef uint32_t ValueType;
- typedef enum
- {
- Generic = 0,
- MachKernel = 1,
- POSIX = 2
+ typedef uint32_t ValueType;
+ typedef enum {
+ Generic = 0,
+ MachKernel = 1,
+ POSIX = 2
#ifdef WITH_SPRINGBOARD
- , SpringBoard = 3
+ ,
+ SpringBoard = 3
#endif
#ifdef WITH_BKS
- , BackBoard = 4
+ ,
+ BackBoard = 4
#endif
#ifdef WITH_FBS
- , FrontBoard = 5
+ ,
+ FrontBoard = 5
#endif
- } FlavorType;
+ } FlavorType;
+
+ explicit DNBError(ValueType err = 0, FlavorType flavor = Generic)
+ : m_err(err), m_flavor(flavor) {}
+
+ const char *AsString() const;
+ void Clear() {
+ m_err = 0;
+ m_flavor = Generic;
+ m_str.clear();
+ }
+ ValueType Error() const { return m_err; }
+ FlavorType Flavor() const { return m_flavor; }
+
+ ValueType operator=(kern_return_t err) {
+ m_err = err;
+ m_flavor = MachKernel;
+ m_str.clear();
+ return m_err;
+ }
+
+ void SetError(kern_return_t err) {
+ m_err = err;
+ m_flavor = MachKernel;
+ m_str.clear();
+ }
+
+ void SetErrorToErrno() {
+ m_err = errno;
+ m_flavor = POSIX;
+ m_str.clear();
+ }
+
+ void SetError(ValueType err, FlavorType flavor) {
+ m_err = err;
+ m_flavor = flavor;
+ m_str.clear();
+ }
+
+ // Generic errors can set their own string values
+ void SetErrorString(const char *err_str) {
+ if (err_str && err_str[0])
+ m_str = err_str;
+ else
+ m_str.clear();
+ }
+ bool Success() const { return m_err == 0; }
+ bool Fail() const { return m_err != 0; }
+ void LogThreadedIfError(const char *format, ...) const;
+ void LogThreaded(const char *format, ...) const;
- explicit DNBError( ValueType err = 0,
- FlavorType flavor = Generic) :
- m_err(err),
- m_flavor(flavor)
- {
- }
-
- const char * AsString() const;
- void Clear() { m_err = 0; m_flavor = Generic; m_str.clear(); }
- ValueType Error() const { return m_err; }
- FlavorType Flavor() const { return m_flavor; }
-
- ValueType operator = (kern_return_t err)
- {
- m_err = err;
- m_flavor = MachKernel;
- m_str.clear();
- return m_err;
- }
-
- void SetError(kern_return_t err)
- {
- m_err = err;
- m_flavor = MachKernel;
- m_str.clear();
- }
-
- void SetErrorToErrno()
- {
- m_err = errno;
- m_flavor = POSIX;
- m_str.clear();
- }
-
- void SetError(ValueType err, FlavorType flavor)
- {
- m_err = err;
- m_flavor = flavor;
- m_str.clear();
- }
-
- // Generic errors can set their own string values
- void SetErrorString(const char *err_str)
- {
- if (err_str && err_str[0])
- m_str = err_str;
- else
- m_str.clear();
- }
- bool Success() const { return m_err == 0; }
- bool Fail() const { return m_err != 0; }
- void LogThreadedIfError(const char *format, ...) const;
- void LogThreaded(const char *format, ...) const;
protected:
- ValueType m_err;
- FlavorType m_flavor;
- mutable std::string m_str;
+ ValueType m_err;
+ FlavorType m_flavor;
+ mutable std::string m_str;
};
-
-#endif // #ifndef __DNBError_h__
+#endif // #ifndef __DNBError_h__
Modified: lldb/trunk/tools/debugserver/source/DNBLog.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBLog.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBLog.cpp (original)
+++ lldb/trunk/tools/debugserver/source/DNBLog.cpp Tue Sep 6 15:57:50 2016
@@ -16,362 +16,272 @@
static int g_debug = 0;
static int g_verbose = 0;
-#if defined (DNBLOG_ENABLED)
+#if defined(DNBLOG_ENABLED)
-#include <stdio.h>
+#include "PThreadMutex.h"
+#include <mach/mach.h>
+#include <pthread.h>
#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
-#include <mach/mach.h>
-#include <pthread.h>
-#include "PThreadMutex.h"
uint32_t g_log_bits = 0;
static DNBCallbackLog g_log_callback = NULL;
static void *g_log_baton = NULL;
+int DNBLogGetDebug() { return g_debug; }
-int
-DNBLogGetDebug ()
-{
- return g_debug;
-}
-
-
-void
-DNBLogSetDebug (int g)
-{
- g_debug = g;
-}
+void DNBLogSetDebug(int g) { g_debug = g; }
-int
-DNBLogGetVerbose ()
-{
- return g_verbose;
-}
+int DNBLogGetVerbose() { return g_verbose; }
-void
-DNBLogSetVerbose (int v)
-{
- g_verbose = v;
-}
+void DNBLogSetVerbose(int v) { g_verbose = v; }
-bool
-DNBLogCheckLogBit (uint32_t bit)
-{
- return (g_log_bits & bit) != 0;
-}
+bool DNBLogCheckLogBit(uint32_t bit) { return (g_log_bits & bit) != 0; }
-uint32_t
-DNBLogSetLogMask (uint32_t mask)
-{
- uint32_t old = g_log_bits;
- g_log_bits = mask;
- return old;
+uint32_t DNBLogSetLogMask(uint32_t mask) {
+ uint32_t old = g_log_bits;
+ g_log_bits = mask;
+ return old;
}
-uint32_t
-DNBLogGetLogMask ()
-{
- return g_log_bits;
-}
+uint32_t DNBLogGetLogMask() { return g_log_bits; }
-void
-DNBLogSetLogCallback (DNBCallbackLog callback, void *baton)
-{
- g_log_callback = callback;
- g_log_baton = baton;
+void DNBLogSetLogCallback(DNBCallbackLog callback, void *baton) {
+ g_log_callback = callback;
+ g_log_baton = baton;
}
-DNBCallbackLog
-DNBLogGetLogCallback ()
-{
- return g_log_callback;
-}
+DNBCallbackLog DNBLogGetLogCallback() { return g_log_callback; }
-bool
-DNBLogEnabled ()
-{
- return g_log_callback != NULL;
-}
+bool DNBLogEnabled() { return g_log_callback != NULL; }
-bool
-DNBLogEnabledForAny (uint32_t mask)
-{
- if (g_log_callback)
- return (g_log_bits & mask) != 0;
- return false;
+bool DNBLogEnabledForAny(uint32_t mask) {
+ if (g_log_callback)
+ return (g_log_bits & mask) != 0;
+ return false;
}
-static inline void
-_DNBLogVAPrintf(uint32_t flags, const char *format, va_list args)
-{
- static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE);
- PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex);
+static inline void _DNBLogVAPrintf(uint32_t flags, const char *format,
+ va_list args) {
+ static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE);
+ PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex);
- if (g_log_callback)
- g_log_callback(g_log_baton, flags, format, args);
+ if (g_log_callback)
+ g_log_callback(g_log_baton, flags, format, args);
}
-void
-_DNBLog(uint32_t flags, const char *format, ...)
-{
- va_list args;
- va_start (args, format);
- _DNBLogVAPrintf(flags, format, args);
- va_end (args);
+void _DNBLog(uint32_t flags, const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ _DNBLogVAPrintf(flags, format, args);
+ va_end(args);
}
//----------------------------------------------------------------------
// Print debug strings if and only if the global g_debug is set to
// a non-zero value.
//----------------------------------------------------------------------
-void
-_DNBLogDebug (const char *format, ...)
-{
- if (DNBLogEnabled () && g_debug)
- {
- va_list args;
- va_start (args, format);
- _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args);
- va_end (args);
- }
+void _DNBLogDebug(const char *format, ...) {
+ if (DNBLogEnabled() && g_debug) {
+ va_list args;
+ va_start(args, format);
+ _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args);
+ va_end(args);
+ }
}
-
//----------------------------------------------------------------------
// Print debug strings if and only if the global g_debug is set to
// a non-zero value.
//----------------------------------------------------------------------
-void
-_DNBLogDebugVerbose (const char *format, ...)
-{
- if (DNBLogEnabled () && g_debug && g_verbose)
- {
- va_list args;
- va_start (args, format);
- _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args);
- va_end (args);
- }
+void _DNBLogDebugVerbose(const char *format, ...) {
+ if (DNBLogEnabled() && g_debug && g_verbose) {
+ va_list args;
+ va_start(args, format);
+ _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args);
+ va_end(args);
+ }
}
-
static uint32_t g_message_id = 0;
//----------------------------------------------------------------------
// Prefix the formatted log string with process and thread IDs and
// suffix it with a newline.
//----------------------------------------------------------------------
-void
-_DNBLogThreaded (const char *format, ...)
-{
- if (DNBLogEnabled ())
- {
- //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
-
- char *arg_msg = NULL;
- va_list args;
- va_start (args, format);
- ::vasprintf (&arg_msg, format, args);
- va_end (args);
-
- if (arg_msg != NULL)
- {
- static struct timeval g_timeval = { 0 , 0 };
- static struct timeval tv;
- static struct timeval delta;
- gettimeofday(&tv, NULL);
- if (g_timeval.tv_sec == 0)
- {
- delta.tv_sec = 0;
- delta.tv_usec = 0;
- }
- else
- {
- timersub (&tv, &g_timeval, &delta);
- }
- g_timeval = tv;
-
- // Calling "mach_port_deallocate()" bumps the reference count on the thread
- // port, so we need to deallocate it. mach_task_self() doesn't bump the ref
- // count.
- thread_port_t thread_self = mach_thread_self();
-
- _DNBLog (DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s",
- ++g_message_id,
- delta.tv_sec,
- delta.tv_usec,
- getpid(),
- thread_self,
- arg_msg);
-
- mach_port_deallocate(mach_task_self(), thread_self);
- free (arg_msg);
- }
+void _DNBLogThreaded(const char *format, ...) {
+ if (DNBLogEnabled()) {
+ // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
+
+ char *arg_msg = NULL;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != NULL) {
+ static struct timeval g_timeval = {0, 0};
+ static struct timeval tv;
+ static struct timeval delta;
+ gettimeofday(&tv, NULL);
+ if (g_timeval.tv_sec == 0) {
+ delta.tv_sec = 0;
+ delta.tv_usec = 0;
+ } else {
+ timersub(&tv, &g_timeval, &delta);
+ }
+ g_timeval = tv;
+
+ // Calling "mach_port_deallocate()" bumps the reference count on the
+ // thread
+ // port, so we need to deallocate it. mach_task_self() doesn't bump the
+ // ref
+ // count.
+ thread_port_t thread_self = mach_thread_self();
+
+ _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s",
+ ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(),
+ thread_self, arg_msg);
+
+ mach_port_deallocate(mach_task_self(), thread_self);
+ free(arg_msg);
}
+ }
}
//----------------------------------------------------------------------
// Prefix the formatted log string with process and thread IDs and
// suffix it with a newline.
//----------------------------------------------------------------------
-void
-_DNBLogThreadedIf (uint32_t log_bit, const char *format, ...)
-{
- if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit)
- {
- //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
-
- char *arg_msg = NULL;
- va_list args;
- va_start (args, format);
- ::vasprintf (&arg_msg, format, args);
- va_end (args);
-
- if (arg_msg != NULL)
- {
- static struct timeval g_timeval = { 0 , 0 };
- static struct timeval tv;
- static struct timeval delta;
- gettimeofday(&tv, NULL);
- if (g_timeval.tv_sec == 0)
- {
- delta.tv_sec = 0;
- delta.tv_usec = 0;
- }
- else
- {
- timersub (&tv, &g_timeval, &delta);
- }
- g_timeval = tv;
-
- // Calling "mach_port_deallocate()" bumps the reference count on the thread
- // port, so we need to deallocate it. mach_task_self() doesn't bump the ref
- // count.
- thread_port_t thread_self = mach_thread_self();
-
- _DNBLog (DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s",
- ++g_message_id,
- delta.tv_sec,
- delta.tv_usec,
- getpid(),
- thread_self,
- arg_msg);
+void _DNBLogThreadedIf(uint32_t log_bit, const char *format, ...) {
+ if (DNBLogEnabled() && (log_bit & g_log_bits) == log_bit) {
+ // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
+
+ char *arg_msg = NULL;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != NULL) {
+ static struct timeval g_timeval = {0, 0};
+ static struct timeval tv;
+ static struct timeval delta;
+ gettimeofday(&tv, NULL);
+ if (g_timeval.tv_sec == 0) {
+ delta.tv_sec = 0;
+ delta.tv_usec = 0;
+ } else {
+ timersub(&tv, &g_timeval, &delta);
+ }
+ g_timeval = tv;
+
+ // Calling "mach_port_deallocate()" bumps the reference count on the
+ // thread
+ // port, so we need to deallocate it. mach_task_self() doesn't bump the
+ // ref
+ // count.
+ thread_port_t thread_self = mach_thread_self();
+
+ _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s",
+ ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(),
+ thread_self, arg_msg);
- mach_port_deallocate(mach_task_self(), thread_self);
+ mach_port_deallocate(mach_task_self(), thread_self);
- free (arg_msg);
- }
+ free(arg_msg);
}
+ }
}
-
-
//----------------------------------------------------------------------
// Printing of errors that are not fatal.
//----------------------------------------------------------------------
-void
-_DNBLogError (const char *format, ...)
-{
- if (DNBLogEnabled ())
- {
- char *arg_msg = NULL;
- va_list args;
- va_start (args, format);
- ::vasprintf (&arg_msg, format, args);
- va_end (args);
-
- if (arg_msg != NULL)
- {
- _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg);
- free (arg_msg);
- }
+void _DNBLogError(const char *format, ...) {
+ if (DNBLogEnabled()) {
+ char *arg_msg = NULL;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != NULL) {
+ _DNBLog(DNBLOG_FLAG_ERROR, "error: %s", arg_msg);
+ free(arg_msg);
}
+ }
}
//----------------------------------------------------------------------
// Printing of errors that ARE fatal. Exit with ERR exit code
// immediately.
//----------------------------------------------------------------------
-void
-_DNBLogFatalError (int err, const char *format, ...)
-{
- if (DNBLogEnabled ())
- {
- char *arg_msg = NULL;
- va_list args;
- va_start (args, format);
- ::vasprintf (&arg_msg, format, args);
- va_end (args);
-
- if (arg_msg != NULL)
- {
- _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg);
- free (arg_msg);
- }
- ::exit (err);
+void _DNBLogFatalError(int err, const char *format, ...) {
+ if (DNBLogEnabled()) {
+ char *arg_msg = NULL;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != NULL) {
+ _DNBLog(DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg);
+ free(arg_msg);
}
+ ::exit(err);
+ }
}
-
//----------------------------------------------------------------------
// Printing of warnings that are not fatal only if verbose mode is
// enabled.
//----------------------------------------------------------------------
-void
-_DNBLogVerbose (const char *format, ...)
-{
- if (DNBLogEnabled () && g_verbose)
- {
- va_list args;
- va_start (args, format);
- _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args);
- va_end (args);
- }
+void _DNBLogVerbose(const char *format, ...) {
+ if (DNBLogEnabled() && g_verbose) {
+ va_list args;
+ va_start(args, format);
+ _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args);
+ va_end(args);
+ }
}
//----------------------------------------------------------------------
// Printing of warnings that are not fatal only if verbose mode is
// enabled.
//----------------------------------------------------------------------
-void
-_DNBLogWarningVerbose (const char *format, ...)
-{
- if (DNBLogEnabled () && g_verbose)
- {
- char *arg_msg = NULL;
- va_list args;
- va_start (args, format);
- ::vasprintf (&arg_msg, format, args);
- va_end (args);
-
- if (arg_msg != NULL)
- {
- _DNBLog (DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg);
- free (arg_msg);
- }
+void _DNBLogWarningVerbose(const char *format, ...) {
+ if (DNBLogEnabled() && g_verbose) {
+ char *arg_msg = NULL;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != NULL) {
+ _DNBLog(DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s",
+ arg_msg);
+ free(arg_msg);
}
+ }
}
//----------------------------------------------------------------------
// Printing of warnings that are not fatal.
//----------------------------------------------------------------------
-void
-_DNBLogWarning (const char *format, ...)
-{
- if (DNBLogEnabled ())
- {
- char *arg_msg = NULL;
- va_list args;
- va_start (args, format);
- ::vasprintf (&arg_msg, format, args);
- va_end (args);
-
- if (arg_msg != NULL)
- {
- _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg);
- free (arg_msg);
- }
+void _DNBLogWarning(const char *format, ...) {
+ if (DNBLogEnabled()) {
+ char *arg_msg = NULL;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != NULL) {
+ _DNBLog(DNBLOG_FLAG_WARNING, "warning: %s", arg_msg);
+ free(arg_msg);
}
+ }
}
#endif
Modified: lldb/trunk/tools/debugserver/source/DNBLog.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBLog.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBLog.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBLog.h Tue Sep 6 15:57:50 2016
@@ -14,78 +14,135 @@
#ifndef __DNBLog_h__
#define __DNBLog_h__
-#include <stdio.h>
-#include <stdint.h>
#include "DNBDefs.h"
+#include <stdint.h>
+#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
-// Flags that get filled in automatically before calling the log callback function
-#define DNBLOG_FLAG_FATAL (1u << 0)
-#define DNBLOG_FLAG_ERROR (1u << 1)
-#define DNBLOG_FLAG_WARNING (1u << 2)
-#define DNBLOG_FLAG_DEBUG (1u << 3)
-#define DNBLOG_FLAG_VERBOSE (1u << 4)
-#define DNBLOG_FLAG_THREADED (1u << 5)
+// Flags that get filled in automatically before calling the log callback
+// function
+#define DNBLOG_FLAG_FATAL (1u << 0)
+#define DNBLOG_FLAG_ERROR (1u << 1)
+#define DNBLOG_FLAG_WARNING (1u << 2)
+#define DNBLOG_FLAG_DEBUG (1u << 3)
+#define DNBLOG_FLAG_VERBOSE (1u << 4)
+#define DNBLOG_FLAG_THREADED (1u << 5)
#define DNBLOG_ENABLED
-#if defined (DNBLOG_ENABLED)
+#if defined(DNBLOG_ENABLED)
-void _DNBLog(uint32_t flags, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
-void _DNBLogDebug (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
-void _DNBLogDebugVerbose (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) ;
-void _DNBLogThreaded (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
-void _DNBLogThreadedIf (uint32_t mask, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
-void _DNBLogError (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
-void _DNBLogFatalError (int err, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
-void _DNBLogVerbose (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
-void _DNBLogWarning (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
-void _DNBLogWarningVerbose (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
-bool DNBLogCheckLogBit (uint32_t bit);
-uint32_t DNBLogSetLogMask (uint32_t mask);
-uint32_t DNBLogGetLogMask ();
-void DNBLogSetLogCallback (DNBCallbackLog callback, void *baton);
-DNBCallbackLog DNBLogGetLogCallback ();
-bool DNBLogEnabled ();
-bool DNBLogEnabledForAny (uint32_t mask);
-int DNBLogGetDebug ();
-void DNBLogSetDebug (int g);
-int DNBLogGetVerbose ();
-void DNBLogSetVerbose (int g);
-
-#define DNBLog(fmt, ...) do { if (DNBLogEnabled()) { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0)
-#define DNBLogDebug(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogDebug(fmt, ## __VA_ARGS__); } } while (0)
-#define DNBLogDebugVerbose(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogDebugVerbose(fmt, ## __VA_ARGS__); } } while (0)
-#define DNBLogThreaded(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogThreaded(fmt, ## __VA_ARGS__); } } while (0)
-#define DNBLogThreadedIf(mask, fmt, ...) do { if (DNBLogEnabledForAny(mask)) { _DNBLogThreaded(fmt, ## __VA_ARGS__); } } while (0)
-#define DNBLogError(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogError(fmt, ## __VA_ARGS__); } } while (0)
-#define DNBLogFatalError(err, fmt, ...) do { if (DNBLogEnabled()) { _DNBLogFatalError(err, fmt, ## __VA_ARGS__); } } while (0)
-#define DNBLogVerbose(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogVerbose(fmt, ## __VA_ARGS__); } } while (0)
-#define DNBLogWarning(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogWarning(fmt, ## __VA_ARGS__); } } while (0)
-#define DNBLogWarningVerbose(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogWarningVerbose(fmt, ## __VA_ARGS__); } } while (0)
-
-#else // #if defined(DNBLOG_ENABLED)
-
-#define DNBLogDebug(...) ((void)0)
-#define DNBLogDebugVerbose(...) ((void)0)
-#define DNBLogThreaded(...) ((void)0)
-#define DNBLogThreadedIf(...) ((void)0)
-#define DNBLogError(...) ((void)0)
-#define DNBLogFatalError(...) ((void)0)
-#define DNBLogVerbose(...) ((void)0)
-#define DNBLogWarning(...) ((void)0)
-#define DNBLogWarningVerbose(...) ((void)0)
-#define DNBLogGetLogFile() ((FILE *)NULL)
-#define DNBLogSetLogFile(f) ((void)0)
-#define DNBLogCheckLogBit(bit) ((bool)false)
-#define DNBLogSetLogMask(mask) ((uint32_t)0u)
-#define DNBLogGetLogMask() ((uint32_t)0u)
-#define DNBLogToASL() ((void)0)
-#define DNBLogToFile() ((void)0)
-#define DNBLogCloseLogFile() ((void)0)
+void _DNBLog(uint32_t flags, const char *format, ...)
+ __attribute__((format(printf, 2, 3)));
+void _DNBLogDebug(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+void _DNBLogDebugVerbose(const char *fmt, ...)
+ __attribute__((format(printf, 1, 2)));
+void _DNBLogThreaded(const char *fmt, ...)
+ __attribute__((format(printf, 1, 2)));
+void _DNBLogThreadedIf(uint32_t mask, const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+void _DNBLogError(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+void _DNBLogFatalError(int err, const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+void _DNBLogVerbose(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+void _DNBLogWarning(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+void _DNBLogWarningVerbose(const char *fmt, ...)
+ __attribute__((format(printf, 1, 2)));
+bool DNBLogCheckLogBit(uint32_t bit);
+uint32_t DNBLogSetLogMask(uint32_t mask);
+uint32_t DNBLogGetLogMask();
+void DNBLogSetLogCallback(DNBCallbackLog callback, void *baton);
+DNBCallbackLog DNBLogGetLogCallback();
+bool DNBLogEnabled();
+bool DNBLogEnabledForAny(uint32_t mask);
+int DNBLogGetDebug();
+void DNBLogSetDebug(int g);
+int DNBLogGetVerbose();
+void DNBLogSetVerbose(int g);
+
+#define DNBLog(fmt, ...) \
+ do { \
+ if (DNBLogEnabled()) { \
+ _DNBLog(0, fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+#define DNBLogDebug(fmt, ...) \
+ do { \
+ if (DNBLogEnabled()) { \
+ _DNBLogDebug(fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+#define DNBLogDebugVerbose(fmt, ...) \
+ do { \
+ if (DNBLogEnabled()) { \
+ _DNBLogDebugVerbose(fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+#define DNBLogThreaded(fmt, ...) \
+ do { \
+ if (DNBLogEnabled()) { \
+ _DNBLogThreaded(fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+#define DNBLogThreadedIf(mask, fmt, ...) \
+ do { \
+ if (DNBLogEnabledForAny(mask)) { \
+ _DNBLogThreaded(fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+#define DNBLogError(fmt, ...) \
+ do { \
+ if (DNBLogEnabled()) { \
+ _DNBLogError(fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+#define DNBLogFatalError(err, fmt, ...) \
+ do { \
+ if (DNBLogEnabled()) { \
+ _DNBLogFatalError(err, fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+#define DNBLogVerbose(fmt, ...) \
+ do { \
+ if (DNBLogEnabled()) { \
+ _DNBLogVerbose(fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+#define DNBLogWarning(fmt, ...) \
+ do { \
+ if (DNBLogEnabled()) { \
+ _DNBLogWarning(fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+#define DNBLogWarningVerbose(fmt, ...) \
+ do { \
+ if (DNBLogEnabled()) { \
+ _DNBLogWarningVerbose(fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+#else // #if defined(DNBLOG_ENABLED)
+
+#define DNBLogDebug(...) ((void)0)
+#define DNBLogDebugVerbose(...) ((void)0)
+#define DNBLogThreaded(...) ((void)0)
+#define DNBLogThreadedIf(...) ((void)0)
+#define DNBLogError(...) ((void)0)
+#define DNBLogFatalError(...) ((void)0)
+#define DNBLogVerbose(...) ((void)0)
+#define DNBLogWarning(...) ((void)0)
+#define DNBLogWarningVerbose(...) ((void)0)
+#define DNBLogGetLogFile() ((FILE *)NULL)
+#define DNBLogSetLogFile(f) ((void)0)
+#define DNBLogCheckLogBit(bit) ((bool)false)
+#define DNBLogSetLogMask(mask) ((uint32_t)0u)
+#define DNBLogGetLogMask() ((uint32_t)0u)
+#define DNBLogToASL() ((void)0)
+#define DNBLogToFile() ((void)0)
+#define DNBLogCloseLogFile() ((void)0)
#endif // #else defined(DNBLOG_ENABLED)
Modified: lldb/trunk/tools/debugserver/source/DNBRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBRegisterInfo.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBRegisterInfo.cpp (original)
+++ lldb/trunk/tools/debugserver/source/DNBRegisterInfo.cpp Tue Sep 6 15:57:50 2016
@@ -15,205 +15,237 @@
#include "DNBLog.h"
#include <string.h>
-DNBRegisterValueClass::DNBRegisterValueClass(const DNBRegisterInfo *regInfo)
-{
- Clear();
- if (regInfo)
- info = *regInfo;
+DNBRegisterValueClass::DNBRegisterValueClass(const DNBRegisterInfo *regInfo) {
+ Clear();
+ if (regInfo)
+ info = *regInfo;
}
-void
-DNBRegisterValueClass::Clear()
-{
- memset(&info, 0, sizeof(DNBRegisterInfo));
- memset(&value, 0, sizeof(value));
+void DNBRegisterValueClass::Clear() {
+ memset(&info, 0, sizeof(DNBRegisterInfo));
+ memset(&value, 0, sizeof(value));
}
-bool
-DNBRegisterValueClass::IsValid() const
-{
- return
- info.name != NULL &&
- info.type != InvalidRegType &&
- info.size > 0 && info.size <= sizeof(value);
+bool DNBRegisterValueClass::IsValid() const {
+ return info.name != NULL && info.type != InvalidRegType && info.size > 0 &&
+ info.size <= sizeof(value);
}
-#define PRINT_COMMA_SEPARATOR do { if (pos < end) { if (i > 0) { strncpy(pos, ", ", end - pos); pos += 2; } } } while (0)
+#define PRINT_COMMA_SEPARATOR \
+ do { \
+ if (pos < end) { \
+ if (i > 0) { \
+ strncpy(pos, ", ", end - pos); \
+ pos += 2; \
+ } \
+ } \
+ } while (0)
+
+void DNBRegisterValueClass::Dump(const char *pre, const char *post) const {
+ if (info.name != NULL) {
+ char str[1024];
+ char *pos;
+ char *end = str + sizeof(str);
+ if (info.format == Hex) {
+ switch (info.size) {
+ case 0:
+ snprintf(str, sizeof(str), "%s",
+ "error: invalid register size of zero.");
+ break;
+ case 1:
+ snprintf(str, sizeof(str), "0x%2.2x", value.uint8);
+ break;
+ case 2:
+ snprintf(str, sizeof(str), "0x%4.4x", value.uint16);
+ break;
+ case 4:
+ snprintf(str, sizeof(str), "0x%8.8x", value.uint32);
+ break;
+ case 8:
+ snprintf(str, sizeof(str), "0x%16.16llx", value.uint64);
+ break;
+ case 16:
+ snprintf(str, sizeof(str), "0x%16.16llx%16.16llx", value.v_uint64[0],
+ value.v_uint64[1]);
+ break;
+ default:
+ strncpy(str, "0x", 3);
+ pos = str + 2;
+ for (uint32_t i = 0; i < info.size; ++i) {
+ if (pos < end)
+ pos +=
+ snprintf(pos, end - pos, "%2.2x", (uint32_t)value.v_uint8[i]);
+ }
+ break;
+ }
+ } else {
+ switch (info.type) {
+ case Uint:
+ switch (info.size) {
+ case 1:
+ snprintf(str, sizeof(str), "%u", value.uint8);
+ break;
+ case 2:
+ snprintf(str, sizeof(str), "%u", value.uint16);
+ break;
+ case 4:
+ snprintf(str, sizeof(str), "%u", value.uint32);
+ break;
+ case 8:
+ snprintf(str, sizeof(str), "%llu", value.uint64);
+ break;
+ default:
+ snprintf(str, sizeof(str), "error: unsupported uint byte size %d.",
+ info.size);
+ break;
+ }
+ break;
-void
-DNBRegisterValueClass::Dump(const char *pre, const char *post) const
-{
- if (info.name != NULL)
- {
- char str[1024];
- char *pos;
- char *end = str + sizeof(str);
- if (info.format == Hex)
- {
- switch (info.size)
- {
- case 0: snprintf(str, sizeof(str), "%s", "error: invalid register size of zero."); break;
- case 1: snprintf(str, sizeof(str), "0x%2.2x", value.uint8); break;
- case 2: snprintf(str, sizeof(str), "0x%4.4x", value.uint16); break;
- case 4: snprintf(str, sizeof(str), "0x%8.8x", value.uint32); break;
- case 8: snprintf(str, sizeof(str), "0x%16.16llx", value.uint64); break;
- case 16: snprintf(str, sizeof(str), "0x%16.16llx%16.16llx", value.v_uint64[0], value.v_uint64[1]); break;
- default:
- strncpy(str, "0x", 3);
- pos = str + 2;
- for (uint32_t i=0; i<info.size; ++i)
- {
- if (pos < end)
- pos += snprintf(pos, end - pos, "%2.2x", (uint32_t)value.v_uint8[i]);
- }
- break;
- }
+ case Sint:
+ switch (info.size) {
+ case 1:
+ snprintf(str, sizeof(str), "%d", value.sint8);
+ break;
+ case 2:
+ snprintf(str, sizeof(str), "%d", value.sint16);
+ break;
+ case 4:
+ snprintf(str, sizeof(str), "%d", value.sint32);
+ break;
+ case 8:
+ snprintf(str, sizeof(str), "%lld", value.sint64);
+ break;
+ default:
+ snprintf(str, sizeof(str), "error: unsupported sint byte size %d.",
+ info.size);
+ break;
}
- else
- {
- switch (info.type)
- {
- case Uint:
- switch (info.size)
- {
- case 1: snprintf(str, sizeof(str), "%u", value.uint8); break;
- case 2: snprintf(str, sizeof(str), "%u", value.uint16); break;
- case 4: snprintf(str, sizeof(str), "%u", value.uint32); break;
- case 8: snprintf(str, sizeof(str), "%llu", value.uint64); break;
- default: snprintf(str, sizeof(str), "error: unsupported uint byte size %d.", info.size); break;
- }
- break;
-
- case Sint:
- switch (info.size)
- {
- case 1: snprintf(str, sizeof(str), "%d", value.sint8); break;
- case 2: snprintf(str, sizeof(str), "%d", value.sint16); break;
- case 4: snprintf(str, sizeof(str), "%d", value.sint32); break;
- case 8: snprintf(str, sizeof(str), "%lld", value.sint64); break;
- default: snprintf(str, sizeof(str), "error: unsupported sint byte size %d.", info.size); break;
- }
- break;
-
- case IEEE754:
- switch (info.size)
- {
- case 4: snprintf(str, sizeof(str), "%f", value.float32); break;
- case 8: snprintf(str, sizeof(str), "%g", value.float64); break;
- default: snprintf(str, sizeof(str), "error: unsupported float byte size %d.", info.size); break;
- }
- break;
-
- case Vector:
- if (info.size > 0)
- {
- switch (info.format)
- {
- case VectorOfSInt8:
- snprintf(str, sizeof(str), "%s", "sint8 { ");
- pos = str + strlen(str);
- for (uint32_t i=0; i<info.size; ++i)
- {
- PRINT_COMMA_SEPARATOR;
- if (pos < end)
- pos += snprintf(pos, end - pos, "%d", (int32_t)value.v_sint8[i]);
- }
- strlcat(str, " }", sizeof(str));
- break;
-
- default:
- DNBLogError("unsupported vector format %d, defaulting to hex bytes.", info.format);
- case VectorOfUInt8:
- snprintf(str, sizeof(str), "%s", "uint8 { ");
- pos = str + strlen(str);
- for (uint32_t i=0; i<info.size; ++i)
- {
- PRINT_COMMA_SEPARATOR;
- if (pos < end)
- pos += snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint8[i]);
- }
- break;
-
- case VectorOfSInt16:
- snprintf(str, sizeof(str), "%s", "sint16 { ");
- pos = str + strlen(str);
- for (uint32_t i=0; i<info.size/2; ++i)
- {
- PRINT_COMMA_SEPARATOR;
- if (pos < end)
- pos += snprintf(pos, end - pos, "%d", (int32_t)value.v_sint16[i]);
- }
- break;
-
- case VectorOfUInt16:
- snprintf(str, sizeof(str), "%s", "uint16 { ");
- pos = str + strlen(str);
- for (uint32_t i=0; i<info.size/2; ++i)
- {
- PRINT_COMMA_SEPARATOR;
- if (pos < end)
- pos += snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint16[i]);
- }
- break;
-
- case VectorOfSInt32:
- snprintf(str, sizeof(str), "%s", "sint32 { ");
- pos = str + strlen(str);
- for (uint32_t i=0; i<info.size/4; ++i)
- {
- PRINT_COMMA_SEPARATOR;
- if (pos < end)
- pos += snprintf(pos, end - pos, "%d", (int32_t)value.v_sint32[i]);
- }
- break;
-
- case VectorOfUInt32:
- snprintf(str, sizeof(str), "%s", "uint32 { ");
- pos = str + strlen(str);
- for (uint32_t i=0; i<info.size/4; ++i)
- {
- PRINT_COMMA_SEPARATOR;
- if (pos < end)
- pos += snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint32[i]);
- }
- break;
-
- case VectorOfFloat32:
- snprintf(str, sizeof(str), "%s", "float32 { ");
- pos = str + strlen(str);
- for (uint32_t i=0; i<info.size/4; ++i)
- {
- PRINT_COMMA_SEPARATOR;
- if (pos < end)
- pos += snprintf(pos, end - pos, "%f", value.v_float32[i]);
- }
- break;
-
- case VectorOfUInt128:
- snprintf(str, sizeof(str), "%s", "uint128 { ");
- pos = str + strlen(str);
- for (uint32_t i=0; i<info.size/16; ++i)
- {
- PRINT_COMMA_SEPARATOR;
- if (pos < end)
- pos += snprintf(pos, end - pos, "0x%16.16llx%16.16llx", value.v_uint64[i], value.v_uint64[i+1]);
- }
- break;
- }
- strlcat(str, " }", sizeof(str));
- }
- else
- {
- snprintf(str, sizeof(str), "error: unsupported vector size %d.", info.size);
- }
- break;
-
- default:
- snprintf(str, sizeof(str), "error: unsupported register type %d.", info.type);
- break;
+ break;
+
+ case IEEE754:
+ switch (info.size) {
+ case 4:
+ snprintf(str, sizeof(str), "%f", value.float32);
+ break;
+ case 8:
+ snprintf(str, sizeof(str), "%g", value.float64);
+ break;
+ default:
+ snprintf(str, sizeof(str), "error: unsupported float byte size %d.",
+ info.size);
+ break;
+ }
+ break;
+
+ case Vector:
+ if (info.size > 0) {
+ switch (info.format) {
+ case VectorOfSInt8:
+ snprintf(str, sizeof(str), "%s", "sint8 { ");
+ pos = str + strlen(str);
+ for (uint32_t i = 0; i < info.size; ++i) {
+ PRINT_COMMA_SEPARATOR;
+ if (pos < end)
+ pos +=
+ snprintf(pos, end - pos, "%d", (int32_t)value.v_sint8[i]);
}
+ strlcat(str, " }", sizeof(str));
+ break;
+
+ default:
+ DNBLogError(
+ "unsupported vector format %d, defaulting to hex bytes.",
+ info.format);
+ case VectorOfUInt8:
+ snprintf(str, sizeof(str), "%s", "uint8 { ");
+ pos = str + strlen(str);
+ for (uint32_t i = 0; i < info.size; ++i) {
+ PRINT_COMMA_SEPARATOR;
+ if (pos < end)
+ pos +=
+ snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint8[i]);
+ }
+ break;
+
+ case VectorOfSInt16:
+ snprintf(str, sizeof(str), "%s", "sint16 { ");
+ pos = str + strlen(str);
+ for (uint32_t i = 0; i < info.size / 2; ++i) {
+ PRINT_COMMA_SEPARATOR;
+ if (pos < end)
+ pos +=
+ snprintf(pos, end - pos, "%d", (int32_t)value.v_sint16[i]);
+ }
+ break;
+
+ case VectorOfUInt16:
+ snprintf(str, sizeof(str), "%s", "uint16 { ");
+ pos = str + strlen(str);
+ for (uint32_t i = 0; i < info.size / 2; ++i) {
+ PRINT_COMMA_SEPARATOR;
+ if (pos < end)
+ pos +=
+ snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint16[i]);
+ }
+ break;
+
+ case VectorOfSInt32:
+ snprintf(str, sizeof(str), "%s", "sint32 { ");
+ pos = str + strlen(str);
+ for (uint32_t i = 0; i < info.size / 4; ++i) {
+ PRINT_COMMA_SEPARATOR;
+ if (pos < end)
+ pos +=
+ snprintf(pos, end - pos, "%d", (int32_t)value.v_sint32[i]);
+ }
+ break;
+
+ case VectorOfUInt32:
+ snprintf(str, sizeof(str), "%s", "uint32 { ");
+ pos = str + strlen(str);
+ for (uint32_t i = 0; i < info.size / 4; ++i) {
+ PRINT_COMMA_SEPARATOR;
+ if (pos < end)
+ pos +=
+ snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint32[i]);
+ }
+ break;
+
+ case VectorOfFloat32:
+ snprintf(str, sizeof(str), "%s", "float32 { ");
+ pos = str + strlen(str);
+ for (uint32_t i = 0; i < info.size / 4; ++i) {
+ PRINT_COMMA_SEPARATOR;
+ if (pos < end)
+ pos += snprintf(pos, end - pos, "%f", value.v_float32[i]);
+ }
+ break;
+
+ case VectorOfUInt128:
+ snprintf(str, sizeof(str), "%s", "uint128 { ");
+ pos = str + strlen(str);
+ for (uint32_t i = 0; i < info.size / 16; ++i) {
+ PRINT_COMMA_SEPARATOR;
+ if (pos < end)
+ pos += snprintf(pos, end - pos, "0x%16.16llx%16.16llx",
+ value.v_uint64[i], value.v_uint64[i + 1]);
+ }
+ break;
+ }
+ strlcat(str, " }", sizeof(str));
+ } else {
+ snprintf(str, sizeof(str), "error: unsupported vector size %d.",
+ info.size);
}
+ break;
- DNBLog("%s%4s = %s%s", pre ? pre : "", info.name, str, post ? post : "");
+ default:
+ snprintf(str, sizeof(str), "error: unsupported register type %d.",
+ info.type);
+ break;
+ }
}
+
+ DNBLog("%s%4s = %s%s", pre ? pre : "", info.name, str, post ? post : "");
+ }
}
Modified: lldb/trunk/tools/debugserver/source/DNBRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBRegisterInfo.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBRegisterInfo.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBRegisterInfo.h Tue Sep 6 15:57:50 2016
@@ -14,17 +14,16 @@
#ifndef __DNBRegisterInfo_h__
#define __DNBRegisterInfo_h__
+#include "DNBDefs.h"
#include <stdint.h>
#include <stdio.h>
-#include "DNBDefs.h"
-struct DNBRegisterValueClass : public DNBRegisterValue
-{
+struct DNBRegisterValueClass : public DNBRegisterValue {
#ifdef __cplusplus
- DNBRegisterValueClass(const DNBRegisterInfo *regInfo = NULL);
- void Clear();
- void Dump(const char *pre, const char *post) const;
- bool IsValid() const;
+ DNBRegisterValueClass(const DNBRegisterInfo *regInfo = NULL);
+ void Clear();
+ void Dump(const char *pre, const char *post) const;
+ bool IsValid() const;
#endif
};
Modified: lldb/trunk/tools/debugserver/source/DNBRuntimeAction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBRuntimeAction.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBRuntimeAction.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBRuntimeAction.h Tue Sep 6 15:57:50 2016
@@ -14,12 +14,11 @@
#ifndef __DNBRuntimeAction_h__
#define __DNBRuntimeAction_h__
-class DNBRuntimeAction
-{
- virtual void Initialize (nub_process_t pid) = 0;
- virtual void ProcessStateChanged (nub_state_t state) = 0;
- virtual void SharedLibraryStateChanged (DNBExecutableImageInfo *image_infos, nub_size_t num_image_infos) = 0;
+class DNBRuntimeAction {
+ virtual void Initialize(nub_process_t pid) = 0;
+ virtual void ProcessStateChanged(nub_state_t state) = 0;
+ virtual void SharedLibraryStateChanged(DNBExecutableImageInfo *image_infos,
+ nub_size_t num_image_infos) = 0;
};
-
#endif // #ifndef __DNBRuntimeAction_h__
Modified: lldb/trunk/tools/debugserver/source/DNBThreadResumeActions.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBThreadResumeActions.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBThreadResumeActions.cpp (original)
+++ lldb/trunk/tools/debugserver/source/DNBThreadResumeActions.cpp Tue Sep 6 15:57:50 2016
@@ -13,104 +13,77 @@
#include "DNBThreadResumeActions.h"
-DNBThreadResumeActions::DNBThreadResumeActions() :
- m_actions (),
- m_signal_handled ()
-{
-}
+DNBThreadResumeActions::DNBThreadResumeActions()
+ : m_actions(), m_signal_handled() {}
-DNBThreadResumeActions::DNBThreadResumeActions (const DNBThreadResumeAction *actions, size_t num_actions) :
- m_actions (),
- m_signal_handled ()
-{
- if (actions && num_actions)
- {
- m_actions.assign (actions, actions + num_actions);
- m_signal_handled.assign (num_actions, false);
- }
+DNBThreadResumeActions::DNBThreadResumeActions(
+ const DNBThreadResumeAction *actions, size_t num_actions)
+ : m_actions(), m_signal_handled() {
+ if (actions && num_actions) {
+ m_actions.assign(actions, actions + num_actions);
+ m_signal_handled.assign(num_actions, false);
+ }
}
-DNBThreadResumeActions::DNBThreadResumeActions (nub_state_t default_action, int signal) :
- m_actions(),
- m_signal_handled ()
-{
- SetDefaultThreadActionIfNeeded (default_action, signal);
-}
-
-void
-DNBThreadResumeActions::Append (const DNBThreadResumeAction &action)
-{
- m_actions.push_back (action);
- m_signal_handled.push_back (false);
-}
-
-void
-DNBThreadResumeActions::AppendAction
-(
- nub_thread_t tid,
- nub_state_t state,
- int signal,
- nub_addr_t addr
-)
-{
- DNBThreadResumeAction action = { tid, state, signal, addr };
- Append (action);
+DNBThreadResumeActions::DNBThreadResumeActions(nub_state_t default_action,
+ int signal)
+ : m_actions(), m_signal_handled() {
+ SetDefaultThreadActionIfNeeded(default_action, signal);
}
-
-const DNBThreadResumeAction *
-DNBThreadResumeActions::GetActionForThread (nub_thread_t tid, bool default_ok) const
-{
- const size_t num_actions = m_actions.size();
- for (size_t i=0; i<num_actions; ++i)
- {
- if (m_actions[i].tid == tid)
- return &m_actions[i];
- }
- if (default_ok && tid != INVALID_NUB_THREAD)
- return GetActionForThread (INVALID_NUB_THREAD, false);
- return NULL;
+void DNBThreadResumeActions::Append(const DNBThreadResumeAction &action) {
+ m_actions.push_back(action);
+ m_signal_handled.push_back(false);
}
-size_t
-DNBThreadResumeActions::NumActionsWithState (nub_state_t state) const
-{
- size_t count = 0;
- const size_t num_actions = m_actions.size();
- for (size_t i=0; i<num_actions; ++i)
- {
- if (m_actions[i].state == state)
- ++count;
- }
- return count;
+void DNBThreadResumeActions::AppendAction(nub_thread_t tid, nub_state_t state,
+ int signal, nub_addr_t addr) {
+ DNBThreadResumeAction action = {tid, state, signal, addr};
+ Append(action);
}
-
-bool
-DNBThreadResumeActions::SetDefaultThreadActionIfNeeded (nub_state_t action, int signal)
-{
- if (GetActionForThread (INVALID_NUB_THREAD, true) == NULL)
- {
- // There isn't a default action so we do need to set it.
- DNBThreadResumeAction default_action = {INVALID_NUB_THREAD, action, signal, INVALID_NUB_ADDRESS };
- m_actions.push_back (default_action);
- m_signal_handled.push_back (false);
- return true; // Return true as we did add the default action
- }
- return false;
+const DNBThreadResumeAction *
+DNBThreadResumeActions::GetActionForThread(nub_thread_t tid,
+ bool default_ok) const {
+ const size_t num_actions = m_actions.size();
+ for (size_t i = 0; i < num_actions; ++i) {
+ if (m_actions[i].tid == tid)
+ return &m_actions[i];
+ }
+ if (default_ok && tid != INVALID_NUB_THREAD)
+ return GetActionForThread(INVALID_NUB_THREAD, false);
+ return NULL;
+}
+
+size_t DNBThreadResumeActions::NumActionsWithState(nub_state_t state) const {
+ size_t count = 0;
+ const size_t num_actions = m_actions.size();
+ for (size_t i = 0; i < num_actions; ++i) {
+ if (m_actions[i].state == state)
+ ++count;
+ }
+ return count;
+}
+
+bool DNBThreadResumeActions::SetDefaultThreadActionIfNeeded(nub_state_t action,
+ int signal) {
+ if (GetActionForThread(INVALID_NUB_THREAD, true) == NULL) {
+ // There isn't a default action so we do need to set it.
+ DNBThreadResumeAction default_action = {INVALID_NUB_THREAD, action, signal,
+ INVALID_NUB_ADDRESS};
+ m_actions.push_back(default_action);
+ m_signal_handled.push_back(false);
+ return true; // Return true as we did add the default action
+ }
+ return false;
}
-
-void
-DNBThreadResumeActions::SetSignalHandledForThread (nub_thread_t tid) const
-{
- if (tid != INVALID_NUB_THREAD)
- {
- const size_t num_actions = m_actions.size();
- for (size_t i=0; i<num_actions; ++i)
- {
- if (m_actions[i].tid == tid)
- m_signal_handled[i] = true;
- }
+void DNBThreadResumeActions::SetSignalHandledForThread(nub_thread_t tid) const {
+ if (tid != INVALID_NUB_THREAD) {
+ const size_t num_actions = m_actions.size();
+ for (size_t i = 0; i < num_actions; ++i) {
+ if (m_actions[i].tid == tid)
+ m_signal_handled[i] = true;
}
+ }
}
Modified: lldb/trunk/tools/debugserver/source/DNBThreadResumeActions.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBThreadResumeActions.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBThreadResumeActions.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBThreadResumeActions.h Tue Sep 6 15:57:50 2016
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef __DNBThreadResumeActions_h__
#define __DNBThreadResumeActions_h__
@@ -19,84 +18,49 @@
#include "DNBDefs.h"
-
-class DNBThreadResumeActions
-{
+class DNBThreadResumeActions {
public:
- DNBThreadResumeActions ();
+ DNBThreadResumeActions();
+
+ DNBThreadResumeActions(nub_state_t default_action, int signal);
+
+ DNBThreadResumeActions(const DNBThreadResumeAction *actions,
+ size_t num_actions);
+
+ bool IsEmpty() const { return m_actions.empty(); }
+
+ void Append(const DNBThreadResumeAction &action);
+
+ void AppendAction(nub_thread_t tid, nub_state_t state, int signal = 0,
+ nub_addr_t addr = INVALID_NUB_ADDRESS);
+
+ void AppendResumeAll() { AppendAction(INVALID_NUB_THREAD, eStateRunning); }
- DNBThreadResumeActions (nub_state_t default_action, int signal);
+ void AppendSuspendAll() { AppendAction(INVALID_NUB_THREAD, eStateStopped); }
- DNBThreadResumeActions (const DNBThreadResumeAction *actions, size_t num_actions);
+ void AppendStepAll() { AppendAction(INVALID_NUB_THREAD, eStateStepping); }
- bool
- IsEmpty() const
- {
- return m_actions.empty();
- }
-
- void
- Append (const DNBThreadResumeAction &action);
-
- void
- AppendAction (nub_thread_t tid,
- nub_state_t state,
- int signal = 0,
- nub_addr_t addr = INVALID_NUB_ADDRESS);
-
- void
- AppendResumeAll ()
- {
- AppendAction (INVALID_NUB_THREAD, eStateRunning);
- }
-
- void
- AppendSuspendAll ()
- {
- AppendAction (INVALID_NUB_THREAD, eStateStopped);
- }
-
- void
- AppendStepAll ()
- {
- AppendAction (INVALID_NUB_THREAD, eStateStepping);
- }
-
- const DNBThreadResumeAction *
- GetActionForThread (nub_thread_t tid, bool default_ok) const;
-
- size_t
- NumActionsWithState (nub_state_t state) const;
-
- bool
- SetDefaultThreadActionIfNeeded (nub_state_t action, int signal);
-
- void
- SetSignalHandledForThread (nub_thread_t tid) const;
-
- const DNBThreadResumeAction *
- GetFirst() const
- {
- return m_actions.data();
- }
-
- size_t
- GetSize () const
- {
- return m_actions.size();
- }
-
- void
- Clear()
- {
- m_actions.clear();
- m_signal_handled.clear();
- }
+ const DNBThreadResumeAction *GetActionForThread(nub_thread_t tid,
+ bool default_ok) const;
+
+ size_t NumActionsWithState(nub_state_t state) const;
+
+ bool SetDefaultThreadActionIfNeeded(nub_state_t action, int signal);
+
+ void SetSignalHandledForThread(nub_thread_t tid) const;
+
+ const DNBThreadResumeAction *GetFirst() const { return m_actions.data(); }
+
+ size_t GetSize() const { return m_actions.size(); }
+
+ void Clear() {
+ m_actions.clear();
+ m_signal_handled.clear();
+ }
protected:
- std::vector<DNBThreadResumeAction> m_actions;
- mutable std::vector<bool> m_signal_handled;
+ std::vector<DNBThreadResumeAction> m_actions;
+ mutable std::vector<bool> m_signal_handled;
};
-
-#endif // #ifndef __DNBThreadResumeActions_h__
+#endif // #ifndef __DNBThreadResumeActions_h__
Modified: lldb/trunk/tools/debugserver/source/DNBTimer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBTimer.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBTimer.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBTimer.h Tue Sep 6 15:57:50 2016
@@ -14,150 +14,132 @@
#ifndef __DNBTimer_h__
#define __DNBTimer_h__
-#include <sys/time.h>
-#include <stdint.h>
-#include <memory>
#include "DNBDefs.h"
#include "PThreadMutex.h"
+#include <memory>
+#include <stdint.h>
+#include <sys/time.h>
-class DNBTimer
-{
+class DNBTimer {
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- DNBTimer (bool threadSafe) :
- m_mutexAP()
- {
- if (threadSafe)
- m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
- Reset();
- }
-
- DNBTimer (const DNBTimer& rhs) :
- m_mutexAP()
- {
- // Create a new mutex to make this timer thread safe as well if
- // the timer we are copying is thread safe
- if (rhs.IsThreadSafe())
- m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
- m_timeval = rhs.m_timeval;
- }
-
- DNBTimer& operator= (const DNBTimer& rhs)
- {
- // Create a new mutex to make this timer thread safe as well if
- // the timer we are copying is thread safe
- if (rhs.IsThreadSafe())
- m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
- m_timeval = rhs.m_timeval;
- return *this;
- }
-
- ~DNBTimer ()
- {
- }
-
- bool
- IsThreadSafe() const
- {
- return m_mutexAP.get() != NULL;
- }
- //------------------------------------------------------------------
- // Reset the time value to now
- //------------------------------------------------------------------
- void
- Reset ()
- {
- PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
- gettimeofday (&m_timeval, NULL);
- }
- //------------------------------------------------------------------
- // Get the total mircoseconds since Jan 1, 1970
- //------------------------------------------------------------------
- uint64_t
- TotalMicroSeconds () const
- {
- PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
- return (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec;
- }
-
- void
- GetTime (uint64_t& sec, uint32_t& usec) const
- {
- PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
- sec = m_timeval.tv_sec;
- usec = m_timeval.tv_usec;
- }
- //------------------------------------------------------------------
- // Return the number of microseconds elapsed between now and the
- // m_timeval
- //------------------------------------------------------------------
- uint64_t
- ElapsedMicroSeconds (bool update)
- {
- PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
- struct timeval now;
- gettimeofday (&now, NULL);
- uint64_t now_usec = (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec;
- uint64_t this_usec = (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec;
- uint64_t elapsed = now_usec - this_usec;
- // Update the timer time value if requeseted
- if (update)
- m_timeval = now;
- return elapsed;
- }
-
- static uint64_t GetTimeOfDay()
- {
- struct timeval now;
- gettimeofday (&now, NULL);
- uint64_t now_usec = (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec;
- return now_usec;
- }
-
- static void OffsetTimeOfDay (struct timespec* ts, __darwin_time_t sec_offset = 0, long nsec_offset = 0)
- {
- if (ts == NULL)
- return;
- // Get the current time in a timeval structure
- struct timeval now;
- gettimeofday (&now, NULL);
- // Morph it into a timespec
- TIMEVAL_TO_TIMESPEC(&now, ts);
- // Offset the timespec if requested
- if (sec_offset != 0 || nsec_offset != 0)
- {
- // Offset the nano seconds
- ts->tv_nsec += nsec_offset;
- // Offset the seconds taking into account a nano-second overflow
- ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset;
- // Trim the nanoseconds back there was an overflow
- ts->tv_nsec = ts->tv_nsec % 1000000000;
- }
- }
- static bool TimeOfDayLaterThan (struct timespec &ts)
- {
- struct timespec now;
- OffsetTimeOfDay(&now);
- if (now.tv_sec > ts.tv_sec)
- return true;
- else if (now.tv_sec < ts.tv_sec)
- return false;
- else
- {
- if (now.tv_nsec > ts.tv_nsec)
- return true;
- else
- return false;
- }
- }
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ DNBTimer(bool threadSafe) : m_mutexAP() {
+ if (threadSafe)
+ m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
+ Reset();
+ }
+
+ DNBTimer(const DNBTimer &rhs) : m_mutexAP() {
+ // Create a new mutex to make this timer thread safe as well if
+ // the timer we are copying is thread safe
+ if (rhs.IsThreadSafe())
+ m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
+ m_timeval = rhs.m_timeval;
+ }
+
+ DNBTimer &operator=(const DNBTimer &rhs) {
+ // Create a new mutex to make this timer thread safe as well if
+ // the timer we are copying is thread safe
+ if (rhs.IsThreadSafe())
+ m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
+ m_timeval = rhs.m_timeval;
+ return *this;
+ }
+
+ ~DNBTimer() {}
+
+ bool IsThreadSafe() const { return m_mutexAP.get() != NULL; }
+ //------------------------------------------------------------------
+ // Reset the time value to now
+ //------------------------------------------------------------------
+ void Reset() {
+ PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get());
+ gettimeofday(&m_timeval, NULL);
+ }
+ //------------------------------------------------------------------
+ // Get the total mircoseconds since Jan 1, 1970
+ //------------------------------------------------------------------
+ uint64_t TotalMicroSeconds() const {
+ PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get());
+ return (uint64_t)(m_timeval.tv_sec) * 1000000ull +
+ (uint64_t)m_timeval.tv_usec;
+ }
+
+ void GetTime(uint64_t &sec, uint32_t &usec) const {
+ PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get());
+ sec = m_timeval.tv_sec;
+ usec = m_timeval.tv_usec;
+ }
+ //------------------------------------------------------------------
+ // Return the number of microseconds elapsed between now and the
+ // m_timeval
+ //------------------------------------------------------------------
+ uint64_t ElapsedMicroSeconds(bool update) {
+ PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get());
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ uint64_t now_usec =
+ (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec;
+ uint64_t this_usec =
+ (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec;
+ uint64_t elapsed = now_usec - this_usec;
+ // Update the timer time value if requeseted
+ if (update)
+ m_timeval = now;
+ return elapsed;
+ }
+
+ static uint64_t GetTimeOfDay() {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ uint64_t now_usec =
+ (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec;
+ return now_usec;
+ }
+
+ static void OffsetTimeOfDay(struct timespec *ts,
+ __darwin_time_t sec_offset = 0,
+ long nsec_offset = 0) {
+ if (ts == NULL)
+ return;
+ // Get the current time in a timeval structure
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ // Morph it into a timespec
+ TIMEVAL_TO_TIMESPEC(&now, ts);
+ // Offset the timespec if requested
+ if (sec_offset != 0 || nsec_offset != 0) {
+ // Offset the nano seconds
+ ts->tv_nsec += nsec_offset;
+ // Offset the seconds taking into account a nano-second overflow
+ ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset;
+ // Trim the nanoseconds back there was an overflow
+ ts->tv_nsec = ts->tv_nsec % 1000000000;
+ }
+ }
+ static bool TimeOfDayLaterThan(struct timespec &ts) {
+ struct timespec now;
+ OffsetTimeOfDay(&now);
+ if (now.tv_sec > ts.tv_sec)
+ return true;
+ else if (now.tv_sec < ts.tv_sec)
+ return false;
+ else {
+ if (now.tv_nsec > ts.tv_nsec)
+ return true;
+ else
+ return false;
+ }
+ }
+
protected:
- //------------------------------------------------------------------
- // Classes that inherit from DNBTimer can see and modify these
- //------------------------------------------------------------------
- std::unique_ptr<PThreadMutex> m_mutexAP;
- struct timeval m_timeval;
+ //------------------------------------------------------------------
+ // Classes that inherit from DNBTimer can see and modify these
+ //------------------------------------------------------------------
+ std::unique_ptr<PThreadMutex> m_mutexAP;
+ struct timeval m_timeval;
};
#endif // #ifndef __DNBTimer_h__
Modified: lldb/trunk/tools/debugserver/source/JSON.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/JSON.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/JSON.cpp (original)
+++ lldb/trunk/tools/debugserver/source/JSON.cpp Tue Sep 6 15:57:50 2016
@@ -14,733 +14,575 @@
#include <limits.h>
// C++ includes
+#include "lldb/Host/StringConvert.h"
#include <iomanip>
#include <sstream>
-#include "lldb/Host/StringConvert.h"
using namespace lldb_private;
-std::string
-JSONString::json_string_quote_metachars (const std::string &s)
-{
- if (s.find('"') == std::string::npos)
- return s;
-
- std::string output;
- const size_t s_size = s.size();
- const char *s_chars = s.c_str();
- for (size_t i = 0; i < s_size; i++)
- {
- unsigned char ch = *(s_chars + i);
- if (ch == '"')
- {
- output.push_back ('\\');
- }
- output.push_back (ch);
- }
- return output;
-}
-
-JSONString::JSONString () :
- JSONValue(JSONValue::Kind::String),
- m_data()
-{
-}
-
-JSONString::JSONString (const char* s) :
- JSONValue(JSONValue::Kind::String),
- m_data(s ? s : "")
-{
-}
-
-JSONString::JSONString (const std::string& s) :
- JSONValue(JSONValue::Kind::String),
- m_data(s)
-{
-}
-
-void
-JSONString::Write (std::ostream& s)
-{
- s << "\"" << json_string_quote_metachars(m_data).c_str() <<"\"";
-}
-
-uint64_t
-JSONNumber::GetAsUnsigned() const
-{
- switch (m_data_type)
- {
- case DataType::Unsigned:
- return m_data.m_unsigned;
- case DataType::Signed:
- return (uint64_t)m_data.m_signed;
- case DataType::Double:
- return (uint64_t)m_data.m_double;
- }
- assert("Unhandled data type");
-}
-
-int64_t
-JSONNumber::GetAsSigned() const
-{
- switch (m_data_type)
- {
- case DataType::Unsigned:
- return (int64_t)m_data.m_unsigned;
- case DataType::Signed:
- return m_data.m_signed;
- case DataType::Double:
- return (int64_t)m_data.m_double;
- }
- assert("Unhandled data type");
-}
-
-double
-JSONNumber::GetAsDouble() const
-{
- switch (m_data_type)
- {
- case DataType::Unsigned:
- return (double)m_data.m_unsigned;
- case DataType::Signed:
- return (double)m_data.m_signed;
- case DataType::Double:
- return m_data.m_double;
- }
- assert("Unhandled data type");
-}
-
-void
-JSONNumber::Write (std::ostream& s)
-{
- switch (m_data_type)
- {
- case DataType::Unsigned:
- s << m_data.m_unsigned;
- break;
- case DataType::Signed:
- s << m_data.m_signed;
- break;
- case DataType::Double:
- // Set max precision to emulate %g.
- s << std::setprecision(std::numeric_limits<double>::digits10 + 1);
- s << m_data.m_double;
- break;
- }
-}
-
-JSONTrue::JSONTrue () :
- JSONValue(JSONValue::Kind::True)
-{
-}
-
-void
-JSONTrue::Write(std::ostream& s)
-{
- s << "true";
-}
-
-JSONFalse::JSONFalse () :
- JSONValue(JSONValue::Kind::False)
-{
-}
-
-void
-JSONFalse::Write(std::ostream& s)
-{
- s << "false";
-}
-
-JSONNull::JSONNull () :
- JSONValue(JSONValue::Kind::Null)
-{
+std::string JSONString::json_string_quote_metachars(const std::string &s) {
+ if (s.find('"') == std::string::npos)
+ return s;
+
+ std::string output;
+ const size_t s_size = s.size();
+ const char *s_chars = s.c_str();
+ for (size_t i = 0; i < s_size; i++) {
+ unsigned char ch = *(s_chars + i);
+ if (ch == '"') {
+ output.push_back('\\');
+ }
+ output.push_back(ch);
+ }
+ return output;
+}
+
+JSONString::JSONString() : JSONValue(JSONValue::Kind::String), m_data() {}
+
+JSONString::JSONString(const char *s)
+ : JSONValue(JSONValue::Kind::String), m_data(s ? s : "") {}
+
+JSONString::JSONString(const std::string &s)
+ : JSONValue(JSONValue::Kind::String), m_data(s) {}
+
+void JSONString::Write(std::ostream &s) {
+ s << "\"" << json_string_quote_metachars(m_data).c_str() << "\"";
+}
+
+uint64_t JSONNumber::GetAsUnsigned() const {
+ switch (m_data_type) {
+ case DataType::Unsigned:
+ return m_data.m_unsigned;
+ case DataType::Signed:
+ return (uint64_t)m_data.m_signed;
+ case DataType::Double:
+ return (uint64_t)m_data.m_double;
+ }
+ assert("Unhandled data type");
+}
+
+int64_t JSONNumber::GetAsSigned() const {
+ switch (m_data_type) {
+ case DataType::Unsigned:
+ return (int64_t)m_data.m_unsigned;
+ case DataType::Signed:
+ return m_data.m_signed;
+ case DataType::Double:
+ return (int64_t)m_data.m_double;
+ }
+ assert("Unhandled data type");
+}
+
+double JSONNumber::GetAsDouble() const {
+ switch (m_data_type) {
+ case DataType::Unsigned:
+ return (double)m_data.m_unsigned;
+ case DataType::Signed:
+ return (double)m_data.m_signed;
+ case DataType::Double:
+ return m_data.m_double;
+ }
+ assert("Unhandled data type");
+}
+
+void JSONNumber::Write(std::ostream &s) {
+ switch (m_data_type) {
+ case DataType::Unsigned:
+ s << m_data.m_unsigned;
+ break;
+ case DataType::Signed:
+ s << m_data.m_signed;
+ break;
+ case DataType::Double:
+ // Set max precision to emulate %g.
+ s << std::setprecision(std::numeric_limits<double>::digits10 + 1);
+ s << m_data.m_double;
+ break;
+ }
+}
+
+JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {}
+
+void JSONTrue::Write(std::ostream &s) { s << "true"; }
+
+JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {}
+
+void JSONFalse::Write(std::ostream &s) { s << "false"; }
+
+JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {}
+
+void JSONNull::Write(std::ostream &s) { s << "null"; }
+
+JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {}
+
+void JSONObject::Write(std::ostream &s) {
+ bool first = true;
+ s << '{';
+ auto iter = m_elements.begin(), end = m_elements.end();
+ for (; iter != end; iter++) {
+ if (first)
+ first = false;
+ else
+ s << ',';
+ JSONString key(iter->first);
+ JSONValue::SP value(iter->second);
+ key.Write(s);
+ s << ':';
+ value->Write(s);
+ }
+ s << '}';
}
-void
-JSONNull::Write(std::ostream& s)
-{
- s << "null";
+bool JSONObject::SetObject(const std::string &key, JSONValue::SP value) {
+ if (key.empty() || nullptr == value.get())
+ return false;
+ m_elements[key] = value;
+ return true;
}
-JSONObject::JSONObject () :
- JSONValue(JSONValue::Kind::Object)
-{
+JSONValue::SP JSONObject::GetObject(const std::string &key) const {
+ auto iter = m_elements.find(key), end = m_elements.end();
+ if (iter == end)
+ return JSONValue::SP();
+ return iter->second;
}
-void
-JSONObject::Write (std::ostream& s)
-{
- bool first = true;
- s << '{';
- auto iter = m_elements.begin(), end = m_elements.end();
- for (;iter != end; iter++)
- {
- if (first)
- first = false;
- else
- s << ',';
- JSONString key(iter->first);
- JSONValue::SP value(iter->second);
- key.Write(s);
- s << ':';
- value->Write(s);
- }
- s << '}';
-}
+bool JSONObject::GetObjectAsBool(const std::string &key, bool &value) const {
+ auto value_sp = GetObject(key);
+ if (!value_sp) {
+ // The given key doesn't exist, so we have no value.
+ return false;
+ }
-bool
-JSONObject::SetObject (const std::string& key,
- JSONValue::SP value)
-{
- if (key.empty() || nullptr == value.get())
- return false;
- m_elements[key] = value;
+ if (JSONTrue::classof(value_sp.get())) {
+ // We have the value, and it is true.
+ value = true;
return true;
+ } else if (JSONFalse::classof(value_sp.get())) {
+ // We have the value, and it is false.
+ value = false;
+ return true;
+ } else {
+ // We don't have a valid bool value for the given key.
+ return false;
+ }
}
-JSONValue::SP
-JSONObject::GetObject (const std::string& key) const
-{
- auto iter = m_elements.find(key), end = m_elements.end();
- if (iter == end)
- return JSONValue::SP();
- return iter->second;
-}
-
-bool
-JSONObject::GetObjectAsBool (const std::string& key, bool& value) const
-{
- auto value_sp = GetObject(key);
- if (!value_sp)
- {
- // The given key doesn't exist, so we have no value.
- return false;
- }
-
- if (JSONTrue::classof(value_sp.get()))
- {
- // We have the value, and it is true.
- value = true;
- return true;
- }
- else if (JSONFalse::classof(value_sp.get()))
- {
- // We have the value, and it is false.
- value = false;
- return true;
- }
- else
- {
- // We don't have a valid bool value for the given key.
- return false;
- }
-}
-
-bool
-JSONObject::GetObjectAsString (const std::string& key, std::string& value) const
-{
- auto value_sp = GetObject(key);
- if (!value_sp)
- {
- // The given key doesn't exist, so we have no value.
- return false;
- }
+bool JSONObject::GetObjectAsString(const std::string &key,
+ std::string &value) const {
+ auto value_sp = GetObject(key);
+ if (!value_sp) {
+ // The given key doesn't exist, so we have no value.
+ return false;
+ }
- if (!JSONString::classof(value_sp.get()))
- return false;
+ if (!JSONString::classof(value_sp.get()))
+ return false;
- value = static_cast<JSONString*>(value_sp.get())->GetData();
- return true;
+ value = static_cast<JSONString *>(value_sp.get())->GetData();
+ return true;
}
-JSONArray::JSONArray () :
- JSONValue(JSONValue::Kind::Array)
-{
-}
+JSONArray::JSONArray() : JSONValue(JSONValue::Kind::Array) {}
-void
-JSONArray::Write (std::ostream& s)
-{
- bool first = true;
- s << '[';
- auto iter = m_elements.begin(), end = m_elements.end();
- for (;iter != end; iter++)
- {
- if (first)
- first = false;
- else
- s << ',';
- (*iter)->Write(s);
- }
- s << ']';
+void JSONArray::Write(std::ostream &s) {
+ bool first = true;
+ s << '[';
+ auto iter = m_elements.begin(), end = m_elements.end();
+ for (; iter != end; iter++) {
+ if (first)
+ first = false;
+ else
+ s << ',';
+ (*iter)->Write(s);
+ }
+ s << ']';
}
-bool
-JSONArray::SetObject (Index i,
- JSONValue::SP value)
-{
- if (value.get() == nullptr)
- return false;
- if (i < m_elements.size())
- {
- m_elements[i] = value;
- return true;
- }
- if (i == m_elements.size())
- {
- m_elements.push_back(value);
- return true;
- }
+bool JSONArray::SetObject(Index i, JSONValue::SP value) {
+ if (value.get() == nullptr)
return false;
-}
-
-bool
-JSONArray::AppendObject (JSONValue::SP value)
-{
- if (value.get() == nullptr)
- return false;
+ if (i < m_elements.size()) {
+ m_elements[i] = value;
+ return true;
+ }
+ if (i == m_elements.size()) {
m_elements.push_back(value);
return true;
+ }
+ return false;
}
-JSONValue::SP
-JSONArray::GetObject (Index i)
-{
- if (i < m_elements.size())
- return m_elements[i];
- return JSONValue::SP();
-}
-
-JSONArray::Size
-JSONArray::GetNumElements ()
-{
- return m_elements.size();
-}
-
-
-JSONParser::JSONParser (const char *cstr) :
- StdStringExtractor(cstr)
-{
-}
-
-JSONParser::Token
-JSONParser::GetToken (std::string &value)
-{
- std::ostringstream error;
-
- value.clear();
- SkipSpaces ();
- const uint64_t start_index = m_index;
- const char ch = GetChar();
- switch (ch)
- {
- case '{': return Token::ObjectStart;
- case '}': return Token::ObjectEnd;
- case '[': return Token::ArrayStart;
- case ']': return Token::ArrayEnd;
- case ',': return Token::Comma;
- case ':': return Token::Colon;
- case '\0': return Token::EndOfFile;
- case 't':
- if (GetChar() == 'r')
- if (GetChar() == 'u')
- if (GetChar() == 'e')
- return Token::True;
- break;
-
- case 'f':
- if (GetChar() == 'a')
- if (GetChar() == 'l')
- if (GetChar() == 's')
- if (GetChar() == 'e')
- return Token::False;
- break;
-
- case 'n':
- if (GetChar() == 'u')
- if (GetChar() == 'l')
- if (GetChar() == 'l')
- return Token::Null;
- break;
-
- case '"':
- {
- while (1)
- {
- bool was_escaped = false;
- int escaped_ch = GetEscapedChar(was_escaped);
- if (escaped_ch == -1)
- {
- error << "error: an error occurred getting a character from offset " <<start_index;
- value = error.str();
- return Token::Error;
-
- }
- else
- {
- const bool is_end_quote = escaped_ch == '"';
- const bool is_null = escaped_ch == 0;
- if (was_escaped || (!is_end_quote && !is_null))
- {
- if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX)
- {
- value.append(1, (char)escaped_ch);
- }
- else
- {
- error << "error: wide character support is needed for unicode character 0x" << std::setprecision(4) << std::hex << escaped_ch;
- error << " at offset " << start_index;
- value = error.str();
- return Token::Error;
- }
- }
- else if (is_end_quote)
- {
- return Token::String;
- }
- else if (is_null)
- {
- value = "error: missing end quote for string";
- return Token::Error;
- }
- }
- }
- }
- break;
-
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- {
- bool done = false;
- bool got_decimal_point = false;
- uint64_t exp_index = 0;
- bool got_int_digits = (ch >= '0') && (ch <= '9');
- bool got_frac_digits = false;
- bool got_exp_digits = false;
- while (!done)
- {
- const char next_ch = PeekChar();
- switch (next_ch)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (exp_index != 0)
- {
- got_exp_digits = true;
- }
- else if (got_decimal_point)
- {
- got_frac_digits = true;
- }
- else
- {
- got_int_digits = true;
- }
- ++m_index; // Skip this character
- break;
-
- case '.':
- if (got_decimal_point)
- {
- error << "error: extra decimal point found at offset " << start_index;
- value = error.str();
- return Token::Error;
- }
- else
- {
- got_decimal_point = true;
- ++m_index; // Skip this character
- }
- break;
-
- case 'e':
- case 'E':
- if (exp_index != 0)
- {
- error << "error: extra exponent character found at offset " << start_index;
- value = error.str();
- return Token::Error;
- }
- else
- {
- exp_index = m_index;
- ++m_index; // Skip this character
- }
- break;
-
- case '+':
- case '-':
- // The '+' and '-' can only come after an exponent character...
- if (exp_index == m_index - 1)
- {
- ++m_index; // Skip the exponent sign character
- }
- else
- {
- error << "error: unexpected " << next_ch << " character at offset " << start_index;
- value = error.str();
- return Token::Error;
- }
- break;
-
- default:
- done = true;
- break;
- }
- }
-
- if (m_index > start_index)
- {
- value = m_packet.substr(start_index, m_index - start_index);
- if (got_decimal_point)
- {
- if (exp_index != 0)
- {
- // We have an exponent, make sure we got exponent digits
- if (got_exp_digits)
- {
- return Token::Float;
- }
- else
- {
- error << "error: got exponent character but no exponent digits at offset in float value \"" << value.c_str() << "\"";
- value = error.str();
- return Token::Error;
- }
- }
- else
- {
- // No exponent, but we need at least one decimal after the decimal point
- if (got_frac_digits)
- {
- return Token::Float;
- }
- else
- {
- error << "error: no digits after decimal point \"" << value.c_str() << "\"";
- value = error.str();
- return Token::Error;
- }
- }
- }
- else
- {
- // No decimal point
- if (got_int_digits)
- {
- // We need at least some integer digits to make an integer
- return Token::Integer;
- }
- else
- {
- error << "error: no digits negate sign \"" << value.c_str() << "\"";
- value = error.str();
- return Token::Error;
- }
- }
- }
- else
- {
- error << "error: invalid number found at offset " << start_index;
- value = error.str();
- return Token::Error;
- }
- }
- break;
- default:
- break;
- }
- error << "error: failed to parse token at offset " << start_index << " (around character '" << ch << "')";
- value = error.str();
- return Token::Error;
-}
-
-int
-JSONParser::GetEscapedChar(bool &was_escaped)
-{
- was_escaped = false;
- const char ch = GetChar();
- if (ch == '\\')
- {
- was_escaped = true;
- const char ch2 = GetChar();
- switch (ch2)
- {
- case '"':
- case '\\':
- case '/':
- default:
- break;
-
- case 'b': return '\b';
- case 'f': return '\f';
- case 'n': return '\n';
- case 'r': return '\r';
- case 't': return '\t';
- case 'u':
- {
- const int hi_byte = DecodeHexU8();
- const int lo_byte = DecodeHexU8();
- if (hi_byte >=0 && lo_byte >= 0)
- return hi_byte << 8 | lo_byte;
- return -1;
- }
- break;
- }
- return ch2;
- }
- return ch;
-}
-
-JSONValue::SP
-JSONParser::ParseJSONObject ()
-{
- // The "JSONParser::Token::ObjectStart" token should have already been consumed
- // by the time this function is called
- std::unique_ptr<JSONObject> dict_up(new JSONObject());
-
- std::string value;
- std::string key;
- while (1)
- {
- JSONParser::Token token = GetToken(value);
-
- if (token == JSONParser::Token::String)
- {
- key.swap(value);
- token = GetToken(value);
- if (token == JSONParser::Token::Colon)
- {
- JSONValue::SP value_sp = ParseJSONValue();
- if (value_sp)
- dict_up->SetObject(key, value_sp);
- else
- break;
- }
- }
- else if (token == JSONParser::Token::ObjectEnd)
- {
- return JSONValue::SP(dict_up.release());
- }
- else if (token == JSONParser::Token::Comma)
- {
- continue;
- }
- else
- {
- break;
- }
- }
- return JSONValue::SP();
+bool JSONArray::AppendObject(JSONValue::SP value) {
+ if (value.get() == nullptr)
+ return false;
+ m_elements.push_back(value);
+ return true;
}
-JSONValue::SP
-JSONParser::ParseJSONArray ()
-{
- // The "JSONParser::Token::ObjectStart" token should have already been consumed
- // by the time this function is called
- std::unique_ptr<JSONArray> array_up(new JSONArray());
-
- std::string value;
- std::string key;
- while (1)
- {
+JSONValue::SP JSONArray::GetObject(Index i) {
+ if (i < m_elements.size())
+ return m_elements[i];
+ return JSONValue::SP();
+}
+
+JSONArray::Size JSONArray::GetNumElements() { return m_elements.size(); }
+
+JSONParser::JSONParser(const char *cstr) : StdStringExtractor(cstr) {}
+
+JSONParser::Token JSONParser::GetToken(std::string &value) {
+ std::ostringstream error;
+
+ value.clear();
+ SkipSpaces();
+ const uint64_t start_index = m_index;
+ const char ch = GetChar();
+ switch (ch) {
+ case '{':
+ return Token::ObjectStart;
+ case '}':
+ return Token::ObjectEnd;
+ case '[':
+ return Token::ArrayStart;
+ case ']':
+ return Token::ArrayEnd;
+ case ',':
+ return Token::Comma;
+ case ':':
+ return Token::Colon;
+ case '\0':
+ return Token::EndOfFile;
+ case 't':
+ if (GetChar() == 'r')
+ if (GetChar() == 'u')
+ if (GetChar() == 'e')
+ return Token::True;
+ break;
+
+ case 'f':
+ if (GetChar() == 'a')
+ if (GetChar() == 'l')
+ if (GetChar() == 's')
+ if (GetChar() == 'e')
+ return Token::False;
+ break;
+
+ case 'n':
+ if (GetChar() == 'u')
+ if (GetChar() == 'l')
+ if (GetChar() == 'l')
+ return Token::Null;
+ break;
+
+ case '"': {
+ while (1) {
+ bool was_escaped = false;
+ int escaped_ch = GetEscapedChar(was_escaped);
+ if (escaped_ch == -1) {
+ error << "error: an error occurred getting a character from offset "
+ << start_index;
+ value = error.str();
+ return Token::Error;
+
+ } else {
+ const bool is_end_quote = escaped_ch == '"';
+ const bool is_null = escaped_ch == 0;
+ if (was_escaped || (!is_end_quote && !is_null)) {
+ if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) {
+ value.append(1, (char)escaped_ch);
+ } else {
+ error << "error: wide character support is needed for unicode "
+ "character 0x"
+ << std::setprecision(4) << std::hex << escaped_ch;
+ error << " at offset " << start_index;
+ value = error.str();
+ return Token::Error;
+ }
+ } else if (is_end_quote) {
+ return Token::String;
+ } else if (is_null) {
+ value = "error: missing end quote for string";
+ return Token::Error;
+ }
+ }
+ }
+ } break;
+
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ bool done = false;
+ bool got_decimal_point = false;
+ uint64_t exp_index = 0;
+ bool got_int_digits = (ch >= '0') && (ch <= '9');
+ bool got_frac_digits = false;
+ bool got_exp_digits = false;
+ while (!done) {
+ const char next_ch = PeekChar();
+ switch (next_ch) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (exp_index != 0) {
+ got_exp_digits = true;
+ } else if (got_decimal_point) {
+ got_frac_digits = true;
+ } else {
+ got_int_digits = true;
+ }
+ ++m_index; // Skip this character
+ break;
+
+ case '.':
+ if (got_decimal_point) {
+ error << "error: extra decimal point found at offset " << start_index;
+ value = error.str();
+ return Token::Error;
+ } else {
+ got_decimal_point = true;
+ ++m_index; // Skip this character
+ }
+ break;
+
+ case 'e':
+ case 'E':
+ if (exp_index != 0) {
+ error << "error: extra exponent character found at offset "
+ << start_index;
+ value = error.str();
+ return Token::Error;
+ } else {
+ exp_index = m_index;
+ ++m_index; // Skip this character
+ }
+ break;
+
+ case '+':
+ case '-':
+ // The '+' and '-' can only come after an exponent character...
+ if (exp_index == m_index - 1) {
+ ++m_index; // Skip the exponent sign character
+ } else {
+ error << "error: unexpected " << next_ch << " character at offset "
+ << start_index;
+ value = error.str();
+ return Token::Error;
+ }
+ break;
+
+ default:
+ done = true;
+ break;
+ }
+ }
+
+ if (m_index > start_index) {
+ value = m_packet.substr(start_index, m_index - start_index);
+ if (got_decimal_point) {
+ if (exp_index != 0) {
+ // We have an exponent, make sure we got exponent digits
+ if (got_exp_digits) {
+ return Token::Float;
+ } else {
+ error << "error: got exponent character but no exponent digits at "
+ "offset in float value \""
+ << value.c_str() << "\"";
+ value = error.str();
+ return Token::Error;
+ }
+ } else {
+ // No exponent, but we need at least one decimal after the decimal
+ // point
+ if (got_frac_digits) {
+ return Token::Float;
+ } else {
+ error << "error: no digits after decimal point \"" << value.c_str()
+ << "\"";
+ value = error.str();
+ return Token::Error;
+ }
+ }
+ } else {
+ // No decimal point
+ if (got_int_digits) {
+ // We need at least some integer digits to make an integer
+ return Token::Integer;
+ } else {
+ error << "error: no digits negate sign \"" << value.c_str() << "\"";
+ value = error.str();
+ return Token::Error;
+ }
+ }
+ } else {
+ error << "error: invalid number found at offset " << start_index;
+ value = error.str();
+ return Token::Error;
+ }
+ } break;
+ default:
+ break;
+ }
+ error << "error: failed to parse token at offset " << start_index
+ << " (around character '" << ch << "')";
+ value = error.str();
+ return Token::Error;
+}
+
+int JSONParser::GetEscapedChar(bool &was_escaped) {
+ was_escaped = false;
+ const char ch = GetChar();
+ if (ch == '\\') {
+ was_escaped = true;
+ const char ch2 = GetChar();
+ switch (ch2) {
+ case '"':
+ case '\\':
+ case '/':
+ default:
+ break;
+
+ case 'b':
+ return '\b';
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'u': {
+ const int hi_byte = DecodeHexU8();
+ const int lo_byte = DecodeHexU8();
+ if (hi_byte >= 0 && lo_byte >= 0)
+ return hi_byte << 8 | lo_byte;
+ return -1;
+ } break;
+ }
+ return ch2;
+ }
+ return ch;
+}
+
+JSONValue::SP JSONParser::ParseJSONObject() {
+ // The "JSONParser::Token::ObjectStart" token should have already been
+ // consumed
+ // by the time this function is called
+ std::unique_ptr<JSONObject> dict_up(new JSONObject());
+
+ std::string value;
+ std::string key;
+ while (1) {
+ JSONParser::Token token = GetToken(value);
+
+ if (token == JSONParser::Token::String) {
+ key.swap(value);
+ token = GetToken(value);
+ if (token == JSONParser::Token::Colon) {
JSONValue::SP value_sp = ParseJSONValue();
if (value_sp)
- array_up->AppendObject(value_sp);
- else
- break;
-
- JSONParser::Token token = GetToken(value);
- if (token == JSONParser::Token::Comma)
- {
- continue;
- }
- else if (token == JSONParser::Token::ArrayEnd)
- {
- return JSONValue::SP(array_up.release());
- }
+ dict_up->SetObject(key, value_sp);
else
- {
- break;
- }
- }
- return JSONValue::SP();
-}
-
-JSONValue::SP
-JSONParser::ParseJSONValue ()
-{
- std::string value;
- const JSONParser::Token token = GetToken(value);
- switch (token)
- {
- case JSONParser::Token::ObjectStart:
- return ParseJSONObject();
-
- case JSONParser::Token::ArrayStart:
- return ParseJSONArray();
-
- case JSONParser::Token::Integer:
- {
- if (value.front() == '-')
- {
- bool success = false;
- int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success);
- if (success)
- return JSONValue::SP(new JSONNumber(sval));
- }
- else
- {
- bool success = false;
- uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
- if (success)
- return JSONValue::SP(new JSONNumber(uval));
- }
- }
- break;
-
- case JSONParser::Token::Float:
- {
- bool success = false;
- double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
- if (success)
- return JSONValue::SP(new JSONNumber(val));
- }
- break;
-
- case JSONParser::Token::String:
- return JSONValue::SP(new JSONString(value));
-
- case JSONParser::Token::True:
- return JSONValue::SP(new JSONTrue());
-
- case JSONParser::Token::False:
- return JSONValue::SP(new JSONFalse());
-
- case JSONParser::Token::Null:
- return JSONValue::SP(new JSONNull());
+ break;
+ }
+ } else if (token == JSONParser::Token::ObjectEnd) {
+ return JSONValue::SP(dict_up.release());
+ } else if (token == JSONParser::Token::Comma) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ return JSONValue::SP();
+}
+
+JSONValue::SP JSONParser::ParseJSONArray() {
+ // The "JSONParser::Token::ObjectStart" token should have already been
+ // consumed
+ // by the time this function is called
+ std::unique_ptr<JSONArray> array_up(new JSONArray());
+
+ std::string value;
+ std::string key;
+ while (1) {
+ JSONValue::SP value_sp = ParseJSONValue();
+ if (value_sp)
+ array_up->AppendObject(value_sp);
+ else
+ break;
- default:
- break;
- }
- return JSONValue::SP();
-
+ JSONParser::Token token = GetToken(value);
+ if (token == JSONParser::Token::Comma) {
+ continue;
+ } else if (token == JSONParser::Token::ArrayEnd) {
+ return JSONValue::SP(array_up.release());
+ } else {
+ break;
+ }
+ }
+ return JSONValue::SP();
+}
+
+JSONValue::SP JSONParser::ParseJSONValue() {
+ std::string value;
+ const JSONParser::Token token = GetToken(value);
+ switch (token) {
+ case JSONParser::Token::ObjectStart:
+ return ParseJSONObject();
+
+ case JSONParser::Token::ArrayStart:
+ return ParseJSONArray();
+
+ case JSONParser::Token::Integer: {
+ if (value.front() == '-') {
+ bool success = false;
+ int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success);
+ if (success)
+ return JSONValue::SP(new JSONNumber(sval));
+ } else {
+ bool success = false;
+ uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
+ if (success)
+ return JSONValue::SP(new JSONNumber(uval));
+ }
+ } break;
+
+ case JSONParser::Token::Float: {
+ bool success = false;
+ double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
+ if (success)
+ return JSONValue::SP(new JSONNumber(val));
+ } break;
+
+ case JSONParser::Token::String:
+ return JSONValue::SP(new JSONString(value));
+
+ case JSONParser::Token::True:
+ return JSONValue::SP(new JSONTrue());
+
+ case JSONParser::Token::False:
+ return JSONValue::SP(new JSONFalse());
+
+ case JSONParser::Token::Null:
+ return JSONValue::SP(new JSONNull());
+
+ default:
+ break;
+ }
+ return JSONValue::SP();
}
Modified: lldb/trunk/tools/debugserver/source/JSON.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/JSON.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/JSON.h (original)
+++ lldb/trunk/tools/debugserver/source/JSON.h Tue Sep 6 15:57:50 2016
@@ -25,358 +25,281 @@
#include <string>
#include <vector>
-class JSONValue
-{
+class JSONValue {
public:
- virtual void
- Write (std::ostream& s) = 0;
-
- typedef std::shared_ptr<JSONValue> SP;
-
- enum class Kind
- {
- String,
- Number,
- True,
- False,
- Null,
- Object,
- Array
- };
-
- JSONValue (Kind k) :
- m_kind(k)
- {}
-
- Kind
- GetKind() const
- {
- return m_kind;
- }
-
- virtual
- ~JSONValue () = default;
-
+ virtual void Write(std::ostream &s) = 0;
+
+ typedef std::shared_ptr<JSONValue> SP;
+
+ enum class Kind { String, Number, True, False, Null, Object, Array };
+
+ JSONValue(Kind k) : m_kind(k) {}
+
+ Kind GetKind() const { return m_kind; }
+
+ virtual ~JSONValue() = default;
+
private:
- const Kind m_kind;
+ const Kind m_kind;
};
-class JSONString : public JSONValue
-{
+class JSONString : public JSONValue {
public:
- JSONString ();
- JSONString (const char* s);
- JSONString (const std::string& s);
-
- JSONString (const JSONString& s) = delete;
- JSONString&
- operator = (const JSONString& s) = delete;
-
- void
- Write(std::ostream& s) override;
-
- typedef std::shared_ptr<JSONString> SP;
-
- std::string
- GetData () { return m_data; }
-
- static bool classof(const JSONValue *V)
- {
- return V->GetKind() == JSONValue::Kind::String;
- }
-
- ~JSONString() override = default;
-
+ JSONString();
+ JSONString(const char *s);
+ JSONString(const std::string &s);
+
+ JSONString(const JSONString &s) = delete;
+ JSONString &operator=(const JSONString &s) = delete;
+
+ void Write(std::ostream &s) override;
+
+ typedef std::shared_ptr<JSONString> SP;
+
+ std::string GetData() { return m_data; }
+
+ static bool classof(const JSONValue *V) {
+ return V->GetKind() == JSONValue::Kind::String;
+ }
+
+ ~JSONString() override = default;
+
private:
-
- static std::string
- json_string_quote_metachars (const std::string&);
-
- std::string m_data;
+ static std::string json_string_quote_metachars(const std::string &);
+
+ std::string m_data;
};
-class JSONNumber : public JSONValue
-{
+class JSONNumber : public JSONValue {
public:
- typedef std::shared_ptr<JSONNumber> SP;
+ typedef std::shared_ptr<JSONNumber> SP;
- // We cretae a constructor for all integer and floating point type with using templates and
- // SFINAE to avoid having ambiguous overloads because of the implicit type promotion. If we
- // would have constructors only with int64_t, uint64_t and double types then constructing a
- // JSONNumber from an int32_t (or any other similar type) would fail to compile.
-
- template <typename T,
- typename std::enable_if<std::is_integral<T>::value &&
- std::is_unsigned<T>::value>::type* = nullptr>
- explicit JSONNumber (T u) :
- JSONValue(JSONValue::Kind::Number),
- m_data_type(DataType::Unsigned)
- {
- m_data.m_unsigned = u;
- }
-
- template <typename T,
- typename std::enable_if<std::is_integral<T>::value &&
- std::is_signed<T>::value>::type* = nullptr>
- explicit JSONNumber (T s) :
- JSONValue(JSONValue::Kind::Number),
- m_data_type(DataType::Signed)
- {
- m_data.m_signed = s;
- }
-
- template <typename T,
- typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
- explicit JSONNumber (T d) :
- JSONValue(JSONValue::Kind::Number),
- m_data_type(DataType::Double)
- {
- m_data.m_double = d;
- }
-
- ~JSONNumber() override = default;
-
- JSONNumber (const JSONNumber& s) = delete;
- JSONNumber&
- operator = (const JSONNumber& s) = delete;
-
- void
- Write(std::ostream& s) override;
-
- uint64_t
- GetAsUnsigned() const;
-
- int64_t
- GetAsSigned() const;
-
- double
- GetAsDouble() const;
-
- static bool classof(const JSONValue *V)
- {
- return V->GetKind() == JSONValue::Kind::Number;
- }
+ // We cretae a constructor for all integer and floating point type with using
+ // templates and
+ // SFINAE to avoid having ambiguous overloads because of the implicit type
+ // promotion. If we
+ // would have constructors only with int64_t, uint64_t and double types then
+ // constructing a
+ // JSONNumber from an int32_t (or any other similar type) would fail to
+ // compile.
+
+ template <typename T, typename std::enable_if<
+ std::is_integral<T>::value &&
+ std::is_unsigned<T>::value>::type * = nullptr>
+ explicit JSONNumber(T u)
+ : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Unsigned) {
+ m_data.m_unsigned = u;
+ }
+
+ template <typename T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_signed<T>::value>::type * = nullptr>
+ explicit JSONNumber(T s)
+ : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Signed) {
+ m_data.m_signed = s;
+ }
+
+ template <typename T, typename std::enable_if<
+ std::is_floating_point<T>::value>::type * = nullptr>
+ explicit JSONNumber(T d)
+ : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Double) {
+ m_data.m_double = d;
+ }
+
+ ~JSONNumber() override = default;
+
+ JSONNumber(const JSONNumber &s) = delete;
+ JSONNumber &operator=(const JSONNumber &s) = delete;
+
+ void Write(std::ostream &s) override;
+
+ uint64_t GetAsUnsigned() const;
+
+ int64_t GetAsSigned() const;
+
+ double GetAsDouble() const;
+
+ static bool classof(const JSONValue *V) {
+ return V->GetKind() == JSONValue::Kind::Number;
+ }
private:
- enum class DataType : uint8_t
- {
- Unsigned,
- Signed,
- Double
- } m_data_type;
-
- union
- {
- uint64_t m_unsigned;
- int64_t m_signed;
- double m_double;
- } m_data;
+ enum class DataType : uint8_t { Unsigned, Signed, Double } m_data_type;
+
+ union {
+ uint64_t m_unsigned;
+ int64_t m_signed;
+ double m_double;
+ } m_data;
};
-class JSONTrue : public JSONValue
-{
+class JSONTrue : public JSONValue {
public:
- JSONTrue ();
+ JSONTrue();
+
+ JSONTrue(const JSONTrue &s) = delete;
+ JSONTrue &operator=(const JSONTrue &s) = delete;
+
+ void Write(std::ostream &s) override;
- JSONTrue (const JSONTrue& s) = delete;
- JSONTrue&
- operator = (const JSONTrue& s) = delete;
-
- void
- Write(std::ostream& s) override;
-
- typedef std::shared_ptr<JSONTrue> SP;
-
- static bool classof(const JSONValue *V)
- {
- return V->GetKind() == JSONValue::Kind::True;
- }
-
- ~JSONTrue() override = default;
+ typedef std::shared_ptr<JSONTrue> SP;
+
+ static bool classof(const JSONValue *V) {
+ return V->GetKind() == JSONValue::Kind::True;
+ }
+
+ ~JSONTrue() override = default;
};
-class JSONFalse : public JSONValue
-{
+class JSONFalse : public JSONValue {
public:
- JSONFalse ();
+ JSONFalse();
+
+ JSONFalse(const JSONFalse &s) = delete;
+ JSONFalse &operator=(const JSONFalse &s) = delete;
+
+ void Write(std::ostream &s) override;
+
+ typedef std::shared_ptr<JSONFalse> SP;
- JSONFalse (const JSONFalse& s) = delete;
- JSONFalse&
- operator = (const JSONFalse& s) = delete;
-
- void
- Write(std::ostream& s) override;
-
- typedef std::shared_ptr<JSONFalse> SP;
-
- static bool classof(const JSONValue *V)
- {
- return V->GetKind() == JSONValue::Kind::False;
- }
-
- ~JSONFalse() override = default;
+ static bool classof(const JSONValue *V) {
+ return V->GetKind() == JSONValue::Kind::False;
+ }
+
+ ~JSONFalse() override = default;
};
-class JSONNull : public JSONValue
-{
+class JSONNull : public JSONValue {
public:
- JSONNull ();
+ JSONNull();
+
+ JSONNull(const JSONNull &s) = delete;
+ JSONNull &operator=(const JSONNull &s) = delete;
+
+ void Write(std::ostream &s) override;
- JSONNull (const JSONNull& s) = delete;
- JSONNull&
- operator = (const JSONNull& s) = delete;
-
- void
- Write(std::ostream& s) override;
-
- typedef std::shared_ptr<JSONNull> SP;
-
- static bool classof(const JSONValue *V)
- {
- return V->GetKind() == JSONValue::Kind::Null;
- }
-
- ~JSONNull() override = default;
+ typedef std::shared_ptr<JSONNull> SP;
+
+ static bool classof(const JSONValue *V) {
+ return V->GetKind() == JSONValue::Kind::Null;
+ }
+
+ ~JSONNull() override = default;
};
-class JSONObject : public JSONValue
-{
+class JSONObject : public JSONValue {
public:
- JSONObject ();
-
- JSONObject (const JSONObject& s) = delete;
- JSONObject&
- operator = (const JSONObject& s) = delete;
-
- void
- Write(std::ostream& s) override;
-
- typedef std::shared_ptr<JSONObject> SP;
-
- static bool classof(const JSONValue *V)
- {
- return V->GetKind() == JSONValue::Kind::Object;
- }
-
- bool
- SetObject (const std::string& key,
- JSONValue::SP value);
-
- JSONValue::SP
- GetObject (const std::string& key) const;
-
- // -------------------------------------------------------------------------
- /// Return keyed value as bool
- ///
- /// @param[in] key
- /// The value of the key to lookup
- ///
- /// @param[out] value
- /// The value of the key as a bool. Undefined if the key doesn't
- /// exist or if the key is not either true or false.
- ///
- /// @return
- /// true if the key existed as was a bool value; false otherwise.
- /// Note the return value is *not* the value of the bool, use
- /// \b value for that.
- // -------------------------------------------------------------------------
- bool
- GetObjectAsBool (const std::string& key, bool& value) const;
+ JSONObject();
+
+ JSONObject(const JSONObject &s) = delete;
+ JSONObject &operator=(const JSONObject &s) = delete;
- bool
- GetObjectAsString (const std::string& key, std::string& value) const;
+ void Write(std::ostream &s) override;
+
+ typedef std::shared_ptr<JSONObject> SP;
+
+ static bool classof(const JSONValue *V) {
+ return V->GetKind() == JSONValue::Kind::Object;
+ }
+
+ bool SetObject(const std::string &key, JSONValue::SP value);
+
+ JSONValue::SP GetObject(const std::string &key) const;
+
+ // -------------------------------------------------------------------------
+ /// Return keyed value as bool
+ ///
+ /// @param[in] key
+ /// The value of the key to lookup
+ ///
+ /// @param[out] value
+ /// The value of the key as a bool. Undefined if the key doesn't
+ /// exist or if the key is not either true or false.
+ ///
+ /// @return
+ /// true if the key existed as was a bool value; false otherwise.
+ /// Note the return value is *not* the value of the bool, use
+ /// \b value for that.
+ // -------------------------------------------------------------------------
+ bool GetObjectAsBool(const std::string &key, bool &value) const;
+
+ bool GetObjectAsString(const std::string &key, std::string &value) const;
+
+ ~JSONObject() override = default;
- ~JSONObject() override = default;
-
private:
- typedef std::map<std::string, JSONValue::SP> Map;
- typedef Map::iterator Iterator;
- Map m_elements;
+ typedef std::map<std::string, JSONValue::SP> Map;
+ typedef Map::iterator Iterator;
+ Map m_elements;
};
-class JSONArray : public JSONValue
-{
+class JSONArray : public JSONValue {
public:
- JSONArray ();
-
- JSONArray (const JSONArray& s) = delete;
- JSONArray&
- operator = (const JSONArray& s) = delete;
-
- void
- Write(std::ostream& s) override;
-
- typedef std::shared_ptr<JSONArray> SP;
-
- static bool classof(const JSONValue *V)
- {
- return V->GetKind() == JSONValue::Kind::Array;
- }
-
+ JSONArray();
+
+ JSONArray(const JSONArray &s) = delete;
+ JSONArray &operator=(const JSONArray &s) = delete;
+
+ void Write(std::ostream &s) override;
+
+ typedef std::shared_ptr<JSONArray> SP;
+
+ static bool classof(const JSONValue *V) {
+ return V->GetKind() == JSONValue::Kind::Array;
+ }
+
private:
- typedef std::vector<JSONValue::SP> Vector;
- typedef Vector::iterator Iterator;
- typedef Vector::size_type Index;
- typedef Vector::size_type Size;
-
+ typedef std::vector<JSONValue::SP> Vector;
+ typedef Vector::iterator Iterator;
+ typedef Vector::size_type Index;
+ typedef Vector::size_type Size;
+
public:
- bool
- SetObject (Index i,
- JSONValue::SP value);
-
- bool
- AppendObject (JSONValue::SP value);
-
- JSONValue::SP
- GetObject (Index i);
-
- Size
- GetNumElements ();
-
- ~JSONArray() override = default;
-
- Vector m_elements;
+ bool SetObject(Index i, JSONValue::SP value);
+
+ bool AppendObject(JSONValue::SP value);
+
+ JSONValue::SP GetObject(Index i);
+
+ Size GetNumElements();
+
+ ~JSONArray() override = default;
+
+ Vector m_elements;
};
-class JSONParser : public StdStringExtractor
-{
+class JSONParser : public StdStringExtractor {
public:
- enum Token
- {
- Invalid,
- Error,
- ObjectStart,
- ObjectEnd,
- ArrayStart,
- ArrayEnd,
- Comma,
- Colon,
- String,
- Integer,
- Float,
- True,
- False,
- Null,
- EndOfFile
- };
-
- JSONParser (const char *cstr);
+ enum Token {
+ Invalid,
+ Error,
+ ObjectStart,
+ ObjectEnd,
+ ArrayStart,
+ ArrayEnd,
+ Comma,
+ Colon,
+ String,
+ Integer,
+ Float,
+ True,
+ False,
+ Null,
+ EndOfFile
+ };
+
+ JSONParser(const char *cstr);
- int
- GetEscapedChar (bool &was_escaped);
+ int GetEscapedChar(bool &was_escaped);
- Token
- GetToken (std::string &value);
+ Token GetToken(std::string &value);
- JSONValue::SP
- ParseJSONValue ();
+ JSONValue::SP ParseJSONValue();
protected:
- JSONValue::SP
- ParseJSONObject ();
+ JSONValue::SP ParseJSONObject();
- JSONValue::SP
- ParseJSONArray ();
+ JSONValue::SP ParseJSONArray();
};
#endif // utility_JSON_h_
Modified: lldb/trunk/tools/debugserver/source/JSONGenerator.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/JSONGenerator.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/JSONGenerator.h (original)
+++ lldb/trunk/tools/debugserver/source/JSONGenerator.h Tue Sep 6 15:57:50 2016
@@ -29,462 +29,291 @@
/// and printing it as a JSON string.
//----------------------------------------------------------------------
-class JSONGenerator
-{
+class JSONGenerator {
public:
+ class Object;
+ class Array;
+ class Integer;
+ class Float;
+ class Boolean;
+ class String;
+ class Dictionary;
+ class Generic;
+
+ typedef std::shared_ptr<Object> ObjectSP;
+ typedef std::shared_ptr<Array> ArraySP;
+ typedef std::shared_ptr<Integer> IntegerSP;
+ typedef std::shared_ptr<Float> FloatSP;
+ typedef std::shared_ptr<Boolean> BooleanSP;
+ typedef std::shared_ptr<String> StringSP;
+ typedef std::shared_ptr<Dictionary> DictionarySP;
+ typedef std::shared_ptr<Generic> GenericSP;
+
+ enum class Type {
+ eTypeInvalid = -1,
+ eTypeNull = 0,
+ eTypeGeneric,
+ eTypeArray,
+ eTypeInteger,
+ eTypeFloat,
+ eTypeBoolean,
+ eTypeString,
+ eTypeDictionary
+ };
+
+ class Object : public std::enable_shared_from_this<Object> {
+ public:
+ Object(Type t = Type::eTypeInvalid) : m_type(t) {}
+
+ virtual ~Object() {}
+
+ virtual bool IsValid() const { return true; }
+
+ virtual void Clear() { m_type = Type::eTypeInvalid; }
+
+ Type GetType() const { return m_type; }
+
+ void SetType(Type t) { m_type = t; }
+
+ Array *GetAsArray() {
+ if (m_type == Type::eTypeArray)
+ return (Array *)this;
+ return NULL;
+ }
+
+ Dictionary *GetAsDictionary() {
+ if (m_type == Type::eTypeDictionary)
+ return (Dictionary *)this;
+ return NULL;
+ }
+
+ Integer *GetAsInteger() {
+ if (m_type == Type::eTypeInteger)
+ return (Integer *)this;
+ return NULL;
+ }
+
+ Float *GetAsFloat() {
+ if (m_type == Type::eTypeFloat)
+ return (Float *)this;
+ return NULL;
+ }
+
+ Boolean *GetAsBoolean() {
+ if (m_type == Type::eTypeBoolean)
+ return (Boolean *)this;
+ return NULL;
+ }
+
+ String *GetAsString() {
+ if (m_type == Type::eTypeString)
+ return (String *)this;
+ return NULL;
+ }
+
+ Generic *GetAsGeneric() {
+ if (m_type == Type::eTypeGeneric)
+ return (Generic *)this;
+ return NULL;
+ }
+
+ virtual void Dump(std::ostream &s) const = 0;
+
+ private:
+ Type m_type;
+ };
+
+ class Array : public Object {
+ public:
+ Array() : Object(Type::eTypeArray) {}
+
+ virtual ~Array() {}
+
+ void AddItem(ObjectSP item) { m_items.push_back(item); }
+
+ void Dump(std::ostream &s) const override {
+ s << "[";
+ const size_t arrsize = m_items.size();
+ for (size_t i = 0; i < arrsize; ++i) {
+ m_items[i]->Dump(s);
+ if (i + 1 < arrsize)
+ s << ",";
+ }
+ s << "]";
+ }
+
+ protected:
+ typedef std::vector<ObjectSP> collection;
+ collection m_items;
+ };
+
+ class Integer : public Object {
+ public:
+ Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {}
+
+ virtual ~Integer() {}
+
+ void SetValue(uint64_t value) { m_value = value; }
+
+ void Dump(std::ostream &s) const override { s << m_value; }
+
+ protected:
+ uint64_t m_value;
+ };
+
+ class Float : public Object {
+ public:
+ Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
+
+ virtual ~Float() {}
+
+ void SetValue(double value) { m_value = value; }
+
+ void Dump(std::ostream &s) const override { s << m_value; }
+
+ protected:
+ double m_value;
+ };
+
+ class Boolean : public Object {
+ public:
+ Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
+
+ virtual ~Boolean() {}
+
+ void SetValue(bool value) { m_value = value; }
+
+ void Dump(std::ostream &s) const override {
+ if (m_value == true)
+ s << "true";
+ else
+ s << "false";
+ }
+
+ protected:
+ bool m_value;
+ };
+
+ class String : public Object {
+ public:
+ String() : Object(Type::eTypeString), m_value() {}
+
+ String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}
+
+ String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}
+
+ void SetValue(const std::string &string) { m_value = string; }
+
+ void Dump(std::ostream &s) const override {
+ std::string quoted;
+ const size_t strsize = m_value.size();
+ for (size_t i = 0; i < strsize; ++i) {
+ char ch = m_value[i];
+ if (ch == '"')
+ quoted.push_back('\\');
+ quoted.push_back(ch);
+ }
+ s << '"' << quoted.c_str() << '"';
+ }
+
+ protected:
+ std::string m_value;
+ };
+
+ class Dictionary : public Object {
+ public:
+ Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
+
+ virtual ~Dictionary() {}
+
+ void AddItem(std::string key, ObjectSP value) {
+ m_dict.push_back(Pair(key, value));
+ }
+
+ void AddIntegerItem(std::string key, uint64_t value) {
+ AddItem(key, ObjectSP(new Integer(value)));
+ }
+
+ void AddFloatItem(std::string key, double value) {
+ AddItem(key, ObjectSP(new Float(value)));
+ }
+
+ void AddStringItem(std::string key, std::string value) {
+ AddItem(key, ObjectSP(new String(std::move(value))));
+ }
+
+ void AddBytesAsHexASCIIString(std::string key, const uint8_t *src,
+ size_t src_len) {
+ if (src && src_len) {
+ std::ostringstream strm;
+ for (size_t i = 0; i < src_len; i++)
+ strm << std::setfill('0') << std::hex << std::right << std::setw(2)
+ << ((uint32_t)(src[i]));
+ AddItem(key, ObjectSP(new String(std::move(strm.str()))));
+ } else {
+ AddItem(key, ObjectSP(new String()));
+ }
+ }
+
+ void AddBooleanItem(std::string key, bool value) {
+ AddItem(key, ObjectSP(new Boolean(value)));
+ }
+
+ void Dump(std::ostream &s) const override {
+ bool have_printed_one_elem = false;
+ s << "{";
+ for (collection::const_iterator iter = m_dict.begin();
+ iter != m_dict.end(); ++iter) {
+ if (have_printed_one_elem == false) {
+ have_printed_one_elem = true;
+ } else {
+ s << ",";
+ }
+ s << "\"" << iter->first.c_str() << "\":";
+ iter->second->Dump(s);
+ }
+ s << "}";
+ }
+
+ protected:
+ // Keep the dictionary as a vector so the dictionary doesn't reorder itself
+ // when you dump it
+ // We aren't accessing keys by name, so this won't affect performance
+ typedef std::pair<std::string, ObjectSP> Pair;
+ typedef std::vector<Pair> collection;
+ collection m_dict;
+ };
+
+ class Null : public Object {
+ public:
+ Null() : Object(Type::eTypeNull) {}
+
+ virtual ~Null() {}
+
+ bool IsValid() const override { return false; }
+
+ void Dump(std::ostream &s) const override { s << "null"; }
+
+ protected:
+ };
+
+ class Generic : public Object {
+ public:
+ explicit Generic(void *object = nullptr)
+ : Object(Type::eTypeGeneric), m_object(object) {}
+
+ void SetValue(void *value) { m_object = value; }
+
+ void *GetValue() const { return m_object; }
+
+ bool IsValid() const override { return m_object != nullptr; }
+
+ void Dump(std::ostream &s) const override;
+
+ private:
+ void *m_object;
+ };
- class Object;
- class Array;
- class Integer;
- class Float;
- class Boolean;
- class String;
- class Dictionary;
- class Generic;
-
- typedef std::shared_ptr<Object> ObjectSP;
- typedef std::shared_ptr<Array> ArraySP;
- typedef std::shared_ptr<Integer> IntegerSP;
- typedef std::shared_ptr<Float> FloatSP;
- typedef std::shared_ptr<Boolean> BooleanSP;
- typedef std::shared_ptr<String> StringSP;
- typedef std::shared_ptr<Dictionary> DictionarySP;
- typedef std::shared_ptr<Generic> GenericSP;
-
- enum class Type
- {
- eTypeInvalid = -1,
- eTypeNull = 0,
- eTypeGeneric,
- eTypeArray,
- eTypeInteger,
- eTypeFloat,
- eTypeBoolean,
- eTypeString,
- eTypeDictionary
- };
-
- class Object :
- public std::enable_shared_from_this<Object>
- {
- public:
-
- Object (Type t = Type::eTypeInvalid) :
- m_type (t)
- {
- }
-
- virtual ~Object ()
- {
- }
-
- virtual bool
- IsValid() const
- {
- return true;
- }
-
- virtual void
- Clear ()
- {
- m_type = Type::eTypeInvalid;
- }
-
- Type
- GetType () const
- {
- return m_type;
- }
-
- void
- SetType (Type t)
- {
- m_type = t;
- }
-
- Array *
- GetAsArray ()
- {
- if (m_type == Type::eTypeArray)
- return (Array *)this;
- return NULL;
- }
-
- Dictionary *
- GetAsDictionary ()
- {
- if (m_type == Type::eTypeDictionary)
- return (Dictionary *)this;
- return NULL;
- }
-
- Integer *
- GetAsInteger ()
- {
- if (m_type == Type::eTypeInteger)
- return (Integer *)this;
- return NULL;
- }
-
- Float *
- GetAsFloat ()
- {
- if (m_type == Type::eTypeFloat)
- return (Float *)this;
- return NULL;
- }
-
- Boolean *
- GetAsBoolean ()
- {
- if (m_type == Type::eTypeBoolean)
- return (Boolean *)this;
- return NULL;
- }
-
- String *
- GetAsString ()
- {
- if (m_type == Type::eTypeString)
- return (String *)this;
- return NULL;
- }
-
- Generic *
- GetAsGeneric()
- {
- if (m_type == Type::eTypeGeneric)
- return (Generic *)this;
- return NULL;
- }
-
- virtual void
- Dump (std::ostream &s) const = 0;
-
- private:
- Type m_type;
- };
-
- class Array : public Object
- {
- public:
- Array () :
- Object (Type::eTypeArray)
- {
- }
-
- virtual
- ~Array()
- {
- }
-
- void
- AddItem(ObjectSP item)
- {
- m_items.push_back(item);
- }
-
- void Dump(std::ostream &s) const override
- {
- s << "[";
- const size_t arrsize = m_items.size();
- for (size_t i = 0; i < arrsize; ++i)
- {
- m_items[i]->Dump(s);
- if (i + 1 < arrsize)
- s << ",";
- }
- s << "]";
- }
-
- protected:
- typedef std::vector<ObjectSP> collection;
- collection m_items;
- };
-
-
- class Integer : public Object
- {
- public:
- Integer (uint64_t value = 0) :
- Object (Type::eTypeInteger),
- m_value (value)
- {
- }
-
- virtual ~Integer()
- {
- }
-
- void
- SetValue (uint64_t value)
- {
- m_value = value;
- }
-
- void Dump(std::ostream &s) const override
- {
- s << m_value;
- }
-
- protected:
- uint64_t m_value;
- };
-
- class Float : public Object
- {
- public:
- Float (double d = 0.0) :
- Object (Type::eTypeFloat),
- m_value (d)
- {
- }
-
- virtual ~Float()
- {
- }
-
- void
- SetValue (double value)
- {
- m_value = value;
- }
-
- void Dump(std::ostream &s) const override
- {
- s << m_value;
- }
-
- protected:
- double m_value;
- };
-
- class Boolean : public Object
- {
- public:
- Boolean (bool b = false) :
- Object (Type::eTypeBoolean),
- m_value (b)
- {
- }
-
- virtual ~Boolean()
- {
- }
-
- void
- SetValue (bool value)
- {
- m_value = value;
- }
-
- void Dump(std::ostream &s) const override
- {
- if (m_value == true)
- s << "true";
- else
- s << "false";
- }
-
- protected:
- bool m_value;
- };
-
-
-
- class String : public Object
- {
- public:
- String () :
- Object (Type::eTypeString),
- m_value ()
- {
- }
-
- String (const std::string &s) :
- Object (Type::eTypeString),
- m_value (s)
- {
- }
-
- String (const std::string &&s) :
- Object (Type::eTypeString),
- m_value (s)
- {
- }
-
- void
- SetValue (const std::string &string)
- {
- m_value = string;
- }
-
- void Dump(std::ostream &s) const override
- {
- std::string quoted;
- const size_t strsize = m_value.size();
- for (size_t i = 0; i < strsize ; ++i)
- {
- char ch = m_value[i];
- if (ch == '"')
- quoted.push_back ('\\');
- quoted.push_back (ch);
- }
- s << '"' << quoted.c_str() << '"';
- }
-
- protected:
- std::string m_value;
- };
-
- class Dictionary : public Object
- {
- public:
- Dictionary () :
- Object (Type::eTypeDictionary),
- m_dict ()
- {
- }
-
- virtual ~Dictionary()
- {
- }
-
- void
- AddItem (std::string key, ObjectSP value)
- {
- m_dict.push_back(Pair(key, value));
- }
-
- void
- AddIntegerItem (std::string key, uint64_t value)
- {
- AddItem (key, ObjectSP (new Integer(value)));
- }
-
- void
- AddFloatItem (std::string key, double value)
- {
- AddItem (key, ObjectSP (new Float(value)));
- }
-
- void
- AddStringItem (std::string key, std::string value)
- {
- AddItem (key, ObjectSP (new String(std::move(value))));
- }
-
- void
- AddBytesAsHexASCIIString (std::string key, const uint8_t *src, size_t src_len)
- {
- if (src && src_len)
- {
- std::ostringstream strm;
- for (size_t i = 0; i < src_len; i++)
- strm << std::setfill('0') << std::hex << std::right << std::setw(2) << ((uint32_t)(src[i]));
- AddItem (key, ObjectSP (new String(std::move(strm.str()))));
- }
- else
- {
- AddItem (key, ObjectSP (new String()));
- }
- }
-
- void
- AddBooleanItem (std::string key, bool value)
- {
- AddItem (key, ObjectSP (new Boolean(value)));
- }
-
- void Dump(std::ostream &s) const override
- {
- bool have_printed_one_elem = false;
- s << "{";
- for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter)
- {
- if (have_printed_one_elem == false)
- {
- have_printed_one_elem = true;
- }
- else
- {
- s << ",";
- }
- s << "\"" << iter->first.c_str() << "\":";
- iter->second->Dump(s);
- }
- s << "}";
- }
-
- protected:
- // Keep the dictionary as a vector so the dictionary doesn't reorder itself when you dump it
- // We aren't accessing keys by name, so this won't affect performance
- typedef std::pair<std::string, ObjectSP> Pair;
- typedef std::vector<Pair> collection;
- collection m_dict;
- };
-
- class Null : public Object
- {
- public:
- Null () :
- Object (Type::eTypeNull)
- {
- }
-
- virtual ~Null()
- {
- }
-
- bool
- IsValid() const override
- {
- return false;
- }
-
- void Dump(std::ostream &s) const override
- {
- s << "null";
- }
-
- protected:
- };
-
- class Generic : public Object
- {
- public:
- explicit Generic(void *object = nullptr)
- : Object(Type::eTypeGeneric)
- , m_object(object)
- {
- }
-
- void
- SetValue(void *value)
- {
- m_object = value;
- }
-
- void *
- GetValue() const
- {
- return m_object;
- }
-
- bool
- IsValid() const override
- {
- return m_object != nullptr;
- }
-
- void Dump(std::ostream &s) const override;
-
- private:
- void *m_object;
- };
-
-}; // class JSONGenerator
-
-
+}; // class JSONGenerator
-#endif // __JSONGenerator_h_
+#endif // __JSONGenerator_h_
Modified: lldb/trunk/tools/debugserver/source/MacOSX/CFBundle.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/CFBundle.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/CFBundle.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/CFBundle.cpp Tue Sep 6 15:57:50 2016
@@ -17,81 +17,63 @@
//----------------------------------------------------------------------
// CFBundle constructor
//----------------------------------------------------------------------
-CFBundle::CFBundle(const char *path) :
- CFReleaser<CFBundleRef>(),
- m_bundle_url()
-{
- if (path && path[0])
- SetPath(path);
+CFBundle::CFBundle(const char *path)
+ : CFReleaser<CFBundleRef>(), m_bundle_url() {
+ if (path && path[0])
+ SetPath(path);
}
//----------------------------------------------------------------------
// CFBundle copy constructor
//----------------------------------------------------------------------
-CFBundle::CFBundle(const CFBundle& rhs) :
- CFReleaser<CFBundleRef>(rhs),
- m_bundle_url(rhs.m_bundle_url)
-{
-
-}
+CFBundle::CFBundle(const CFBundle &rhs)
+ : CFReleaser<CFBundleRef>(rhs), m_bundle_url(rhs.m_bundle_url) {}
//----------------------------------------------------------------------
// CFBundle copy constructor
//----------------------------------------------------------------------
-CFBundle&
-CFBundle::operator=(const CFBundle& rhs)
-{
- *this = rhs;
- return *this;
+CFBundle &CFBundle::operator=(const CFBundle &rhs) {
+ *this = rhs;
+ return *this;
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-CFBundle::~CFBundle()
-{
-}
+CFBundle::~CFBundle() {}
//----------------------------------------------------------------------
// Set the path for a bundle by supplying a
//----------------------------------------------------------------------
-bool
-CFBundle::SetPath (const char *path)
-{
- CFAllocatorRef alloc = kCFAllocatorDefault;
- // Release our old bundle and ULR
- reset(); // This class is a CFReleaser<CFBundleRef>
- m_bundle_url.reset();
- // Make a CFStringRef from the supplied path
- CFString cf_path;
- cf_path.SetFileSystemRepresentation(path);
- if (cf_path.get())
- {
- // Make our Bundle URL
- m_bundle_url.reset (::CFURLCreateWithFileSystemPath (alloc, cf_path.get(), kCFURLPOSIXPathStyle, true));
- if (m_bundle_url.get())
- {
- reset (::CFBundleCreate (alloc, m_bundle_url.get()));
- }
+bool CFBundle::SetPath(const char *path) {
+ CFAllocatorRef alloc = kCFAllocatorDefault;
+ // Release our old bundle and ULR
+ reset(); // This class is a CFReleaser<CFBundleRef>
+ m_bundle_url.reset();
+ // Make a CFStringRef from the supplied path
+ CFString cf_path;
+ cf_path.SetFileSystemRepresentation(path);
+ if (cf_path.get()) {
+ // Make our Bundle URL
+ m_bundle_url.reset(::CFURLCreateWithFileSystemPath(
+ alloc, cf_path.get(), kCFURLPOSIXPathStyle, true));
+ if (m_bundle_url.get()) {
+ reset(::CFBundleCreate(alloc, m_bundle_url.get()));
}
- return get() != NULL;
+ }
+ return get() != NULL;
}
-CFStringRef
-CFBundle::GetIdentifier () const
-{
- CFBundleRef bundle = get();
- if (bundle != NULL)
- return ::CFBundleGetIdentifier (bundle);
- return NULL;
-}
-
-
-CFURLRef
-CFBundle::CopyExecutableURL () const
-{
- CFBundleRef bundle = get();
- if (bundle != NULL)
- return CFBundleCopyExecutableURL(bundle);
- return NULL;
+CFStringRef CFBundle::GetIdentifier() const {
+ CFBundleRef bundle = get();
+ if (bundle != NULL)
+ return ::CFBundleGetIdentifier(bundle);
+ return NULL;
+}
+
+CFURLRef CFBundle::CopyExecutableURL() const {
+ CFBundleRef bundle = get();
+ if (bundle != NULL)
+ return CFBundleCopyExecutableURL(bundle);
+ return NULL;
}
Modified: lldb/trunk/tools/debugserver/source/MacOSX/CFBundle.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/CFBundle.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/CFBundle.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/CFBundle.h Tue Sep 6 15:57:50 2016
@@ -16,28 +16,23 @@
#include "CFUtils.h"
-class CFBundle : public CFReleaser<CFBundleRef>
-{
+class CFBundle : public CFReleaser<CFBundleRef> {
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- CFBundle(const char *path = NULL);
- CFBundle(const CFBundle& rhs);
- CFBundle& operator=(const CFBundle& rhs);
- virtual
- ~CFBundle();
- bool
- SetPath (const char *path);
-
- CFStringRef
- GetIdentifier () const;
-
- CFURLRef
- CopyExecutableURL () const;
-
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CFBundle(const char *path = NULL);
+ CFBundle(const CFBundle &rhs);
+ CFBundle &operator=(const CFBundle &rhs);
+ virtual ~CFBundle();
+ bool SetPath(const char *path);
+
+ CFStringRef GetIdentifier() const;
+
+ CFURLRef CopyExecutableURL() const;
+
protected:
- CFReleaser<CFURLRef> m_bundle_url;
+ CFReleaser<CFURLRef> m_bundle_url;
};
#endif // #ifndef __CFBundle_h__
Modified: lldb/trunk/tools/debugserver/source/MacOSX/CFString.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/CFString.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/CFString.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/CFString.cpp Tue Sep 6 15:57:50 2016
@@ -12,136 +12,110 @@
//===----------------------------------------------------------------------===//
#include "CFString.h"
-#include <string>
#include <glob.h>
+#include <string>
//----------------------------------------------------------------------
// CFString constructor
//----------------------------------------------------------------------
-CFString::CFString(CFStringRef s) :
- CFReleaser<CFStringRef> (s)
-{
-}
+CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {}
//----------------------------------------------------------------------
// CFString copy constructor
//----------------------------------------------------------------------
-CFString::CFString(const CFString& rhs) :
- CFReleaser<CFStringRef> (rhs)
-{
-
-}
+CFString::CFString(const CFString &rhs) : CFReleaser<CFStringRef>(rhs) {}
//----------------------------------------------------------------------
// CFString copy constructor
//----------------------------------------------------------------------
-CFString&
-CFString::operator=(const CFString& rhs)
-{
- if (this != &rhs)
- *this = rhs;
- return *this;
+CFString &CFString::operator=(const CFString &rhs) {
+ if (this != &rhs)
+ *this = rhs;
+ return *this;
}
-CFString::CFString (const char *cstr, CFStringEncoding cstr_encoding) :
- CFReleaser<CFStringRef> ()
-{
- if (cstr && cstr[0])
- {
- reset(::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
- }
+CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding)
+ : CFReleaser<CFStringRef>() {
+ if (cstr && cstr[0]) {
+ reset(
+ ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
+ }
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-CFString::~CFString()
-{
-}
+CFString::~CFString() {}
-const char *
-CFString::GetFileSystemRepresentation(std::string& s)
-{
- return CFString::FileSystemRepresentation(get(), s);
+const char *CFString::GetFileSystemRepresentation(std::string &s) {
+ return CFString::FileSystemRepresentation(get(), s);
}
-CFStringRef
-CFString::SetFileSystemRepresentation (const char *path)
-{
- CFStringRef new_value = NULL;
- if (path && path[0])
- new_value = ::CFStringCreateWithFileSystemRepresentation (kCFAllocatorDefault, path);
- reset(new_value);
- return get();
-}
-
-
-CFStringRef
-CFString::SetFileSystemRepresentationFromCFType (CFTypeRef cf_type)
-{
- CFStringRef new_value = NULL;
- if (cf_type != NULL)
- {
- CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
-
- if (cf_type_id == ::CFStringGetTypeID())
- {
- // Retain since we are using the existing object
- new_value = (CFStringRef)::CFRetain(cf_type);
- }
- else if (cf_type_id == ::CFURLGetTypeID())
- {
- new_value = ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
- }
+CFStringRef CFString::SetFileSystemRepresentation(const char *path) {
+ CFStringRef new_value = NULL;
+ if (path && path[0])
+ new_value =
+ ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
+ reset(new_value);
+ return get();
+}
+
+CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
+ CFStringRef new_value = NULL;
+ if (cf_type != NULL) {
+ CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
+
+ if (cf_type_id == ::CFStringGetTypeID()) {
+ // Retain since we are using the existing object
+ new_value = (CFStringRef)::CFRetain(cf_type);
+ } else if (cf_type_id == ::CFURLGetTypeID()) {
+ new_value =
+ ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
}
- reset(new_value);
- return get();
+ }
+ reset(new_value);
+ return get();
}
CFStringRef
-CFString::SetFileSystemRepresentationAndExpandTilde (const char *path)
-{
- std::string expanded_path;
- if (CFString::GlobPath(path, expanded_path))
- SetFileSystemRepresentation(expanded_path.c_str());
- else
- reset();
- return get();
+CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
+ std::string expanded_path;
+ if (CFString::GlobPath(path, expanded_path))
+ SetFileSystemRepresentation(expanded_path.c_str());
+ else
+ reset();
+ return get();
}
-const char *
-CFString::UTF8(std::string& str)
-{
- return CFString::UTF8(get(), str);
+const char *CFString::UTF8(std::string &str) {
+ return CFString::UTF8(get(), str);
}
// Static function that puts a copy of the UTF8 contents of CF_STR into STR
-// and returns the C string pointer that is contained in STR when successful, else
-// NULL is returned. This allows the std::string parameter to own the extracted string,
-// and also allows that string to be returned as a C string pointer that can be used.
-
-const char *
-CFString::UTF8 (CFStringRef cf_str, std::string& str)
-{
- if (cf_str)
- {
- const CFStringEncoding encoding = kCFStringEncodingUTF8;
- CFIndex max_utf8_str_len = CFStringGetLength (cf_str);
- max_utf8_str_len = CFStringGetMaximumSizeForEncoding (max_utf8_str_len, encoding);
- if (max_utf8_str_len > 0)
- {
- str.resize(max_utf8_str_len);
- if (!str.empty())
- {
- if (CFStringGetCString (cf_str, &str[0], str.size(), encoding))
- {
- str.resize(strlen(str.c_str()));
- return str.c_str();
- }
- }
+// and returns the C string pointer that is contained in STR when successful,
+// else
+// NULL is returned. This allows the std::string parameter to own the extracted
+// string,
+// and also allows that string to be returned as a C string pointer that can be
+// used.
+
+const char *CFString::UTF8(CFStringRef cf_str, std::string &str) {
+ if (cf_str) {
+ const CFStringEncoding encoding = kCFStringEncodingUTF8;
+ CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
+ max_utf8_str_len =
+ CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
+ if (max_utf8_str_len > 0) {
+ str.resize(max_utf8_str_len);
+ if (!str.empty()) {
+ if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
+ str.resize(strlen(str.c_str()));
+ return str.c_str();
}
+ }
}
- return NULL;
+ }
+ return NULL;
}
// Static function that puts a copy of the file system representation of CF_STR
@@ -150,52 +124,40 @@ CFString::UTF8 (CFStringRef cf_str, std:
// to own the extracted string, and also allows that string to be returned as
// a C string pointer that can be used.
-const char *
-CFString::FileSystemRepresentation (CFStringRef cf_str, std::string& str)
-{
- if (cf_str)
- {
- CFIndex max_length = ::CFStringGetMaximumSizeOfFileSystemRepresentation (cf_str);
- if (max_length > 0)
- {
- str.resize(max_length);
- if (!str.empty())
- {
- if (::CFStringGetFileSystemRepresentation (cf_str, &str[0], str.size()))
- {
- str.erase(::strlen(str.c_str()));
- return str.c_str();
- }
- }
+const char *CFString::FileSystemRepresentation(CFStringRef cf_str,
+ std::string &str) {
+ if (cf_str) {
+ CFIndex max_length =
+ ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str);
+ if (max_length > 0) {
+ str.resize(max_length);
+ if (!str.empty()) {
+ if (::CFStringGetFileSystemRepresentation(cf_str, &str[0],
+ str.size())) {
+ str.erase(::strlen(str.c_str()));
+ return str.c_str();
}
+ }
}
- str.erase();
- return NULL;
-}
-
+ }
+ str.erase();
+ return NULL;
+}
+
+CFIndex CFString::GetLength() const {
+ CFStringRef str = get();
+ if (str)
+ return CFStringGetLength(str);
+ return 0;
+}
+
+const char *CFString::GlobPath(const char *path, std::string &expanded_path) {
+ glob_t globbuf;
+ if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
+ expanded_path = globbuf.gl_pathv[0];
+ ::globfree(&globbuf);
+ } else
+ expanded_path.clear();
-CFIndex
-CFString::GetLength() const
-{
- CFStringRef str = get();
- if (str)
- return CFStringGetLength (str);
- return 0;
+ return expanded_path.c_str();
}
-
-
-const char*
-CFString::GlobPath(const char* path, std::string &expanded_path)
-{
- glob_t globbuf;
- if (::glob (path, GLOB_TILDE, NULL, &globbuf) == 0)
- {
- expanded_path = globbuf.gl_pathv[0];
- ::globfree (&globbuf);
- }
- else
- expanded_path.clear();
-
- return expanded_path.c_str();
-}
-
Modified: lldb/trunk/tools/debugserver/source/MacOSX/CFString.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/CFString.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/CFString.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/CFString.h Tue Sep 6 15:57:50 2016
@@ -17,27 +17,27 @@
#include "CFUtils.h"
#include <iosfwd>
-class CFString : public CFReleaser<CFStringRef>
-{
+class CFString : public CFReleaser<CFStringRef> {
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- CFString (CFStringRef cf_str = NULL);
- CFString (const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8);
- CFString (const CFString& rhs);
- CFString& operator= (const CFString& rhs);
- virtual ~CFString ();
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CFString(CFStringRef cf_str = NULL);
+ CFString(const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8);
+ CFString(const CFString &rhs);
+ CFString &operator=(const CFString &rhs);
+ virtual ~CFString();
- const char * GetFileSystemRepresentation (std::string& str);
- CFStringRef SetFileSystemRepresentation (const char *path);
- CFStringRef SetFileSystemRepresentationFromCFType (CFTypeRef cf_type);
- CFStringRef SetFileSystemRepresentationAndExpandTilde (const char *path);
- const char * UTF8 (std::string& str);
- CFIndex GetLength() const;
- static const char *UTF8 (CFStringRef cf_str, std::string& str);
- static const char *FileSystemRepresentation (CFStringRef cf_str, std::string& str);
- static const char* GlobPath(const char* path, std::string &expanded_path);
+ const char *GetFileSystemRepresentation(std::string &str);
+ CFStringRef SetFileSystemRepresentation(const char *path);
+ CFStringRef SetFileSystemRepresentationFromCFType(CFTypeRef cf_type);
+ CFStringRef SetFileSystemRepresentationAndExpandTilde(const char *path);
+ const char *UTF8(std::string &str);
+ CFIndex GetLength() const;
+ static const char *UTF8(CFStringRef cf_str, std::string &str);
+ static const char *FileSystemRepresentation(CFStringRef cf_str,
+ std::string &str);
+ static const char *GlobPath(const char *path, std::string &expanded_path);
};
#endif // #ifndef __CFString_h__
Modified: lldb/trunk/tools/debugserver/source/MacOSX/CFUtils.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/CFUtils.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/CFUtils.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/CFUtils.h Tue Sep 6 15:57:50 2016
@@ -23,59 +23,56 @@
// call CFRelease() on any valid pointer it owns unless that pointer is
// explicitly released using the release() member function.
//----------------------------------------------------------------------
-template <class T>
-class CFReleaser
-{
+template <class T> class CFReleaser {
public:
- // Type names for the avlue
- typedef T element_type;
+ // Type names for the avlue
+ typedef T element_type;
- // Constructors and destructors
- CFReleaser(T ptr = NULL) : _ptr(ptr) { }
- CFReleaser(const CFReleaser& copy) : _ptr(copy.get())
- {
- if (get())
- ::CFRetain(get());
- }
- virtual ~CFReleaser() { reset(); }
-
- // Assignments
- CFReleaser& operator= (const CFReleaser<T>& copy)
- {
- if (copy != *this)
- {
- // Replace our owned pointer with the new one
- reset(copy.get());
- // Retain the current pointer that we own
- if (get())
- ::CFRetain(get());
- }
- }
- // Get the address of the contained type
- T * ptr_address() { return &_ptr; }
-
- // Access the pointer itself
- const T get() const { return _ptr; }
- T get() { return _ptr; }
-
- // Set a new value for the pointer and CFRelease our old
- // value if we had a valid one.
- void reset(T ptr = NULL)
- {
- if (ptr != _ptr)
- {
- if (_ptr != NULL)
- ::CFRelease(_ptr);
- _ptr = ptr;
- }
- }
+ // Constructors and destructors
+ CFReleaser(T ptr = NULL) : _ptr(ptr) {}
+ CFReleaser(const CFReleaser ©) : _ptr(copy.get()) {
+ if (get())
+ ::CFRetain(get());
+ }
+ virtual ~CFReleaser() { reset(); }
+
+ // Assignments
+ CFReleaser &operator=(const CFReleaser<T> ©) {
+ if (copy != *this) {
+ // Replace our owned pointer with the new one
+ reset(copy.get());
+ // Retain the current pointer that we own
+ if (get())
+ ::CFRetain(get());
+ }
+ }
+ // Get the address of the contained type
+ T *ptr_address() { return &_ptr; }
+
+ // Access the pointer itself
+ const T get() const { return _ptr; }
+ T get() { return _ptr; }
+
+ // Set a new value for the pointer and CFRelease our old
+ // value if we had a valid one.
+ void reset(T ptr = NULL) {
+ if (ptr != _ptr) {
+ if (_ptr != NULL)
+ ::CFRelease(_ptr);
+ _ptr = ptr;
+ }
+ }
+
+ // Release ownership without calling CFRelease
+ T release() {
+ T tmp = _ptr;
+ _ptr = NULL;
+ return tmp;
+ }
- // Release ownership without calling CFRelease
- T release() { T tmp = _ptr; _ptr = NULL; return tmp; }
private:
- element_type _ptr;
+ element_type _ptr;
};
-#endif // #ifdef __cplusplus
-#endif // #ifndef __CFUtils_h__
-
+#endif // #ifdef __cplusplus
+#endif // #ifndef __CFUtils_h__
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp Tue Sep 6 15:57:50 2016
@@ -9,10 +9,6 @@
#include "ActivityStore.h"
-ActivityStore::ActivityStore()
-{
-}
+ActivityStore::ActivityStore() {}
-ActivityStore::~ActivityStore()
-{
-}
+ActivityStore::~ActivityStore() {}
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h Tue Sep 6 15:57:50 2016
@@ -14,23 +14,17 @@
#include "ActivityStreamSPI.h"
-class ActivityStore
-{
+class ActivityStore {
public:
+ virtual ~ActivityStore();
- virtual
- ~ActivityStore();
+ virtual const char *GetActivityForID(os_activity_id_t activity_id) const = 0;
- virtual const char*
- GetActivityForID(os_activity_id_t activity_id) const = 0;
-
- virtual std::string
- GetActivityChainForID(os_activity_id_t activity_id) const = 0;
+ virtual std::string
+ GetActivityChainForID(os_activity_id_t activity_id) const = 0;
protected:
-
- ActivityStore();
-
+ ActivityStore();
};
#endif /* ActivityStore_h */
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h Tue Sep 6 15:57:50 2016
@@ -17,48 +17,45 @@
// Enums
-enum
-{
- OS_ACTIVITY_STREAM_PROCESS_ONLY = 0x00000001,
- OS_ACTIVITY_STREAM_SKIP_DECODE = 0x00000002,
- OS_ACTIVITY_STREAM_PAYLOAD = 0x00000004,
- OS_ACTIVITY_STREAM_HISTORICAL = 0x00000008,
- OS_ACTIVITY_STREAM_CALLSTACK = 0x00000010,
- OS_ACTIVITY_STREAM_DEBUG = 0x00000020,
- OS_ACTIVITY_STREAM_BUFFERED = 0x00000040,
- OS_ACTIVITY_STREAM_NO_SENSITIVE = 0x00000080,
- OS_ACTIVITY_STREAM_INFO = 0x00000100,
- OS_ACTIVITY_STREAM_PROMISCUOUS = 0x00000200,
- OS_ACTIVITY_STREAM_PRECISE_TIMESTAMPS = 0x00000200
+enum {
+ OS_ACTIVITY_STREAM_PROCESS_ONLY = 0x00000001,
+ OS_ACTIVITY_STREAM_SKIP_DECODE = 0x00000002,
+ OS_ACTIVITY_STREAM_PAYLOAD = 0x00000004,
+ OS_ACTIVITY_STREAM_HISTORICAL = 0x00000008,
+ OS_ACTIVITY_STREAM_CALLSTACK = 0x00000010,
+ OS_ACTIVITY_STREAM_DEBUG = 0x00000020,
+ OS_ACTIVITY_STREAM_BUFFERED = 0x00000040,
+ OS_ACTIVITY_STREAM_NO_SENSITIVE = 0x00000080,
+ OS_ACTIVITY_STREAM_INFO = 0x00000100,
+ OS_ACTIVITY_STREAM_PROMISCUOUS = 0x00000200,
+ OS_ACTIVITY_STREAM_PRECISE_TIMESTAMPS = 0x00000200
};
typedef uint32_t os_activity_stream_flag_t;
-enum
-{
- OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE = 0x0201,
- OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION = 0x0202,
- OS_ACTIVITY_STREAM_TYPE_ACTIVITY_USERACTION = 0x0203,
-
- OS_ACTIVITY_STREAM_TYPE_TRACE_MESSAGE = 0x0300,
-
- OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE = 0x0400,
- OS_ACTIVITY_STREAM_TYPE_LEGACY_LOG_MESSAGE = 0x0480,
-
- OS_ACTIVITY_STREAM_TYPE_SIGNPOST_BEGIN = 0x0601,
- OS_ACTIVITY_STREAM_TYPE_SIGNPOST_END = 0x0602,
- OS_ACTIVITY_STREAM_TYPE_SIGNPOST_EVENT = 0x0603,
+enum {
+ OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE = 0x0201,
+ OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION = 0x0202,
+ OS_ACTIVITY_STREAM_TYPE_ACTIVITY_USERACTION = 0x0203,
- OS_ACTIVITY_STREAM_TYPE_STATEDUMP_EVENT = 0x0A00,
+ OS_ACTIVITY_STREAM_TYPE_TRACE_MESSAGE = 0x0300,
+
+ OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE = 0x0400,
+ OS_ACTIVITY_STREAM_TYPE_LEGACY_LOG_MESSAGE = 0x0480,
+
+ OS_ACTIVITY_STREAM_TYPE_SIGNPOST_BEGIN = 0x0601,
+ OS_ACTIVITY_STREAM_TYPE_SIGNPOST_END = 0x0602,
+ OS_ACTIVITY_STREAM_TYPE_SIGNPOST_EVENT = 0x0603,
+
+ OS_ACTIVITY_STREAM_TYPE_STATEDUMP_EVENT = 0x0A00,
};
typedef uint32_t os_activity_stream_type_t;
-enum
-{
- OS_ACTIVITY_STREAM_EVENT_STARTED = 1,
- OS_ACTIVITY_STREAM_EVENT_STOPPED = 2,
- OS_ACTIVITY_STREAM_EVENT_FAILED = 3,
- OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED = 4,
- OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED = 5,
+enum {
+ OS_ACTIVITY_STREAM_EVENT_STARTED = 1,
+ OS_ACTIVITY_STREAM_EVENT_STOPPED = 2,
+ OS_ACTIVITY_STREAM_EVENT_FAILED = 3,
+ OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED = 4,
+ OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED = 5,
};
typedef uint32_t os_activity_stream_event_t;
@@ -68,105 +65,104 @@ typedef uint64_t os_activity_id_t;
typedef struct os_activity_stream_s *os_activity_stream_t;
typedef struct os_activity_stream_entry_s *os_activity_stream_entry_t;
-#define OS_ACTIVITY_STREAM_COMMON() \
- uint64_t trace_id; \
- uint64_t timestamp; \
- uint64_t thread; \
- const uint8_t *image_uuid; \
- const char *image_path; \
- struct timeval tv_gmt; \
- struct timezone tz; \
- uint32_t offset \
-
+#define OS_ACTIVITY_STREAM_COMMON() \
+ uint64_t trace_id; \
+ uint64_t timestamp; \
+ uint64_t thread; \
+ const uint8_t *image_uuid; \
+ const char *image_path; \
+ struct timeval tv_gmt; \
+ struct timezone tz; \
+ uint32_t offset
typedef struct os_activity_stream_common_s {
- OS_ACTIVITY_STREAM_COMMON();
-} *os_activity_stream_common_t;
+ OS_ACTIVITY_STREAM_COMMON();
+} * os_activity_stream_common_t;
struct os_activity_create_s {
- OS_ACTIVITY_STREAM_COMMON();
- const char *name;
- os_activity_id_t creator_aid;
- uint64_t unique_pid;
+ OS_ACTIVITY_STREAM_COMMON();
+ const char *name;
+ os_activity_id_t creator_aid;
+ uint64_t unique_pid;
};
struct os_activity_transition_s {
- OS_ACTIVITY_STREAM_COMMON();
- os_activity_id_t transition_id;
+ OS_ACTIVITY_STREAM_COMMON();
+ os_activity_id_t transition_id;
};
typedef struct os_log_message_s {
- OS_ACTIVITY_STREAM_COMMON();
- const char *format;
- const uint8_t *buffer;
- size_t buffer_sz;
- const uint8_t *privdata;
- size_t privdata_sz;
- const char *subsystem;
- const char *category;
- uint32_t oversize_id;
- uint8_t ttl;
- bool persisted;
-} *os_log_message_t;
+ OS_ACTIVITY_STREAM_COMMON();
+ const char *format;
+ const uint8_t *buffer;
+ size_t buffer_sz;
+ const uint8_t *privdata;
+ size_t privdata_sz;
+ const char *subsystem;
+ const char *category;
+ uint32_t oversize_id;
+ uint8_t ttl;
+ bool persisted;
+} * os_log_message_t;
typedef struct os_trace_message_v2_s {
- OS_ACTIVITY_STREAM_COMMON();
- const char *format;
- const void *buffer;
- size_t bufferLen;
- xpc_object_t __unsafe_unretained payload;
-} *os_trace_message_v2_t;
+ OS_ACTIVITY_STREAM_COMMON();
+ const char *format;
+ const void *buffer;
+ size_t bufferLen;
+ xpc_object_t __unsafe_unretained payload;
+} * os_trace_message_v2_t;
typedef struct os_activity_useraction_s {
- OS_ACTIVITY_STREAM_COMMON();
- const char *action;
- bool persisted;
-} *os_activity_useraction_t;
+ OS_ACTIVITY_STREAM_COMMON();
+ const char *action;
+ bool persisted;
+} * os_activity_useraction_t;
typedef struct os_signpost_s {
- OS_ACTIVITY_STREAM_COMMON();
- const char *format;
- const uint8_t *buffer;
- size_t buffer_sz;
- const uint8_t *privdata;
- size_t privdata_sz;
- const char *subsystem;
- const char *category;
- uint64_t duration_nsec;
- uint32_t callstack_depth;
- uint64_t callstack[OS_ACTIVITY_MAX_CALLSTACK];
-} *os_signpost_t;
+ OS_ACTIVITY_STREAM_COMMON();
+ const char *format;
+ const uint8_t *buffer;
+ size_t buffer_sz;
+ const uint8_t *privdata;
+ size_t privdata_sz;
+ const char *subsystem;
+ const char *category;
+ uint64_t duration_nsec;
+ uint32_t callstack_depth;
+ uint64_t callstack[OS_ACTIVITY_MAX_CALLSTACK];
+} * os_signpost_t;
typedef struct os_activity_statedump_s {
- OS_ACTIVITY_STREAM_COMMON();
- char *message;
- size_t message_size;
- char image_path_buffer[PATH_MAX];
-} *os_activity_statedump_t;
+ OS_ACTIVITY_STREAM_COMMON();
+ char *message;
+ size_t message_size;
+ char image_path_buffer[PATH_MAX];
+} * os_activity_statedump_t;
struct os_activity_stream_entry_s {
- os_activity_stream_type_t type;
+ os_activity_stream_type_t type;
- // information about the process streaming the data
- pid_t pid;
- uint64_t proc_id;
- const uint8_t *proc_imageuuid;
- const char *proc_imagepath;
-
- // the activity associated with this streamed event
- os_activity_id_t activity_id;
- os_activity_id_t parent_id;
-
- union {
- struct os_activity_stream_common_s common;
- struct os_activity_create_s activity_create;
- struct os_activity_transition_s activity_transition;
- struct os_log_message_s log_message;
- struct os_trace_message_v2_s trace_message;
- struct os_activity_useraction_s useraction;
- struct os_signpost_s signpost;
- struct os_activity_statedump_s statedump;
- };
+ // information about the process streaming the data
+ pid_t pid;
+ uint64_t proc_id;
+ const uint8_t *proc_imageuuid;
+ const char *proc_imagepath;
+
+ // the activity associated with this streamed event
+ os_activity_id_t activity_id;
+ os_activity_id_t parent_id;
+
+ union {
+ struct os_activity_stream_common_s common;
+ struct os_activity_create_s activity_create;
+ struct os_activity_transition_s activity_transition;
+ struct os_log_message_s log_message;
+ struct os_trace_message_v2_s trace_message;
+ struct os_activity_useraction_s useraction;
+ struct os_signpost_s signpost;
+ struct os_activity_statedump_s statedump;
+ };
};
// Blocks
@@ -175,26 +171,21 @@ typedef bool (^os_activity_stream_block_
int error);
typedef void (^os_activity_stream_event_block_t)(
- os_activity_stream_t stream,
- os_activity_stream_event_t event);
+ os_activity_stream_t stream, os_activity_stream_event_t event);
// SPI entry point prototypes
-typedef os_activity_stream_t
- (*os_activity_stream_for_pid_t)(pid_t pid, os_activity_stream_flag_t flags,
- os_activity_stream_block_t stream_block);
-
-typedef void
-(*os_activity_stream_resume_t)(os_activity_stream_t stream);
-
-typedef void
- (*os_activity_stream_cancel_t)(os_activity_stream_t stream);
-
-typedef char *
- (*os_log_copy_formatted_message_t)(os_log_message_t log_message);
-
-typedef void
- (*os_activity_stream_set_event_handler_t)
- (os_activity_stream_t stream, os_activity_stream_event_block_t block);
+typedef os_activity_stream_t (*os_activity_stream_for_pid_t)(
+ pid_t pid, os_activity_stream_flag_t flags,
+ os_activity_stream_block_t stream_block);
+
+typedef void (*os_activity_stream_resume_t)(os_activity_stream_t stream);
+
+typedef void (*os_activity_stream_cancel_t)(os_activity_stream_t stream);
+
+typedef char *(*os_log_copy_formatted_message_t)(os_log_message_t log_message);
+
+typedef void (*os_activity_stream_set_event_handler_t)(
+ os_activity_stream_t stream, os_activity_stream_event_block_t block);
#endif /* ActivityStreamSPI_h */
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp Tue Sep 6 15:57:50 2016
@@ -16,9 +16,9 @@
#include <mutex>
#include <vector>
-#include "DarwinLogTypes.h"
#include "DNB.h"
#include "DNBLog.h"
+#include "DarwinLogTypes.h"
#include "LogFilterChain.h"
#include "LogFilterExactMatch.h"
#include "LogFilterRegex.h"
@@ -30,806 +30,668 @@
// Use an anonymous namespace for variables and methods that have no
// reason to leak out through the interface.
-namespace
-{
- /// Specify max depth that the activity parent-child chain will search
- /// back to get the full activity chain name. If we do more than this,
- /// we assume either we hit a loop or it's just too long.
- static const size_t MAX_ACTIVITY_CHAIN_DEPTH = 10;
-
- // Used to tap into and retrieve logs from target process.
- // (Consumer of os_log).
- static os_activity_stream_for_pid_t s_os_activity_stream_for_pid;
- static os_activity_stream_resume_t s_os_activity_stream_resume;
- static os_activity_stream_cancel_t s_os_activity_stream_cancel;
- static os_log_copy_formatted_message_t s_os_log_copy_formatted_message;
- static os_activity_stream_set_event_handler_t
+namespace {
+/// Specify max depth that the activity parent-child chain will search
+/// back to get the full activity chain name. If we do more than this,
+/// we assume either we hit a loop or it's just too long.
+static const size_t MAX_ACTIVITY_CHAIN_DEPTH = 10;
+
+// Used to tap into and retrieve logs from target process.
+// (Consumer of os_log).
+static os_activity_stream_for_pid_t s_os_activity_stream_for_pid;
+static os_activity_stream_resume_t s_os_activity_stream_resume;
+static os_activity_stream_cancel_t s_os_activity_stream_cancel;
+static os_log_copy_formatted_message_t s_os_log_copy_formatted_message;
+static os_activity_stream_set_event_handler_t
s_os_activity_stream_set_event_handler;
- bool
- LookupSPICalls()
- {
- static std::once_flag s_once_flag;
- static bool s_has_spi;
-
- std::call_once(s_once_flag, [] {
- s_os_activity_stream_for_pid = (os_activity_stream_for_pid_t)
- dlsym(RTLD_DEFAULT, "os_activity_stream_for_pid");
- s_os_activity_stream_resume = (os_activity_stream_resume_t)
- dlsym(RTLD_DEFAULT, "os_activity_stream_resume");
- s_os_activity_stream_cancel = (os_activity_stream_cancel_t)
- dlsym(RTLD_DEFAULT, "os_activity_stream_cancel");
- s_os_log_copy_formatted_message = (os_log_copy_formatted_message_t)
- dlsym(RTLD_DEFAULT, "os_log_copy_formatted_message");
- s_os_activity_stream_set_event_handler =
- (os_activity_stream_set_event_handler_t)
- dlsym(RTLD_DEFAULT, "os_activity_stream_set_event_handler");
-
- // We'll indicate we're all set if every function entry point
- // was found.
- s_has_spi =
- (s_os_activity_stream_for_pid != nullptr) &&
+bool LookupSPICalls() {
+ static std::once_flag s_once_flag;
+ static bool s_has_spi;
+
+ std::call_once(s_once_flag, [] {
+ s_os_activity_stream_for_pid = (os_activity_stream_for_pid_t)dlsym(
+ RTLD_DEFAULT, "os_activity_stream_for_pid");
+ s_os_activity_stream_resume = (os_activity_stream_resume_t)dlsym(
+ RTLD_DEFAULT, "os_activity_stream_resume");
+ s_os_activity_stream_cancel = (os_activity_stream_cancel_t)dlsym(
+ RTLD_DEFAULT, "os_activity_stream_cancel");
+ s_os_log_copy_formatted_message = (os_log_copy_formatted_message_t)dlsym(
+ RTLD_DEFAULT, "os_log_copy_formatted_message");
+ s_os_activity_stream_set_event_handler =
+ (os_activity_stream_set_event_handler_t)dlsym(
+ RTLD_DEFAULT, "os_activity_stream_set_event_handler");
+
+ // We'll indicate we're all set if every function entry point
+ // was found.
+ s_has_spi = (s_os_activity_stream_for_pid != nullptr) &&
(s_os_activity_stream_resume != nullptr) &&
(s_os_activity_stream_cancel != nullptr) &&
(s_os_log_copy_formatted_message != nullptr) &&
(s_os_activity_stream_set_event_handler != nullptr);
- if (s_has_spi)
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG, "Found os_log SPI calls.");
- // Tell LogMessageOsLog how to format messages when search
- // criteria requires it.
- LogMessageOsLog::SetFormatterFunction(
- s_os_log_copy_formatted_message);
- }
- else
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG, "Failed to find os_log SPI "
- "calls.");
- }
- });
-
- return s_has_spi;
- }
-
- using Mutex = std::mutex;
- static Mutex s_collector_mutex;
- static std::vector<DarwinLogCollectorSP> s_collectors;
-
- static void
- TrackCollector(const DarwinLogCollectorSP &collector_sp)
- {
- std::lock_guard<Mutex> locker(s_collector_mutex);
- if (std::find(s_collectors.begin(), s_collectors.end(), collector_sp)
- != s_collectors.end())
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "attempted to add same collector multiple times");
- return;
- }
- s_collectors.push_back(collector_sp);
- }
-
- static void
- StopTrackingCollector(const DarwinLogCollectorSP &collector_sp)
- {
- std::lock_guard<Mutex> locker(s_collector_mutex);
- s_collectors.erase(std::remove(s_collectors.begin(), s_collectors.end(),
- collector_sp),
- s_collectors.end());
- }
-
- static DarwinLogCollectorSP
- FindCollectorForProcess(pid_t pid)
- {
- std::lock_guard<Mutex> locker(s_collector_mutex);
- for (const auto &collector_sp : s_collectors)
- {
- if (collector_sp && (collector_sp->GetProcessID() == pid))
- return collector_sp;
- }
- return DarwinLogCollectorSP();
- }
+ if (s_has_spi) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Found os_log SPI calls.");
+ // Tell LogMessageOsLog how to format messages when search
+ // criteria requires it.
+ LogMessageOsLog::SetFormatterFunction(s_os_log_copy_formatted_message);
+ } else {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Failed to find os_log SPI "
+ "calls.");
+ }
+ });
+
+ return s_has_spi;
+}
+
+using Mutex = std::mutex;
+static Mutex s_collector_mutex;
+static std::vector<DarwinLogCollectorSP> s_collectors;
+
+static void TrackCollector(const DarwinLogCollectorSP &collector_sp) {
+ std::lock_guard<Mutex> locker(s_collector_mutex);
+ if (std::find(s_collectors.begin(), s_collectors.end(), collector_sp) !=
+ s_collectors.end()) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "attempted to add same collector multiple times");
+ return;
+ }
+ s_collectors.push_back(collector_sp);
+}
+
+static void StopTrackingCollector(const DarwinLogCollectorSP &collector_sp) {
+ std::lock_guard<Mutex> locker(s_collector_mutex);
+ s_collectors.erase(
+ std::remove(s_collectors.begin(), s_collectors.end(), collector_sp),
+ s_collectors.end());
+}
+
+static DarwinLogCollectorSP FindCollectorForProcess(pid_t pid) {
+ std::lock_guard<Mutex> locker(s_collector_mutex);
+ for (const auto &collector_sp : s_collectors) {
+ if (collector_sp && (collector_sp->GetProcessID() == pid))
+ return collector_sp;
+ }
+ return DarwinLogCollectorSP();
+}
+
+static FilterTarget TargetStringToEnum(const std::string &filter_target_name) {
+ if (filter_target_name == "activity")
+ return eFilterTargetActivity;
+ else if (filter_target_name == "activity-chain")
+ return eFilterTargetActivityChain;
+ else if (filter_target_name == "category")
+ return eFilterTargetCategory;
+ else if (filter_target_name == "message")
+ return eFilterTargetMessage;
+ else if (filter_target_name == "subsystem")
+ return eFilterTargetSubsystem;
+ else
+ return eFilterTargetInvalid;
+}
+
+class Configuration {
+public:
+ Configuration(const JSONObject &config)
+ : m_is_valid(false),
+ m_activity_stream_flags(OS_ACTIVITY_STREAM_PROCESS_ONLY),
+ m_filter_chain_sp(nullptr) {
+ // Parse out activity stream flags
+ if (!ParseSourceFlags(config)) {
+ m_is_valid = false;
+ return;
+ }
+
+ // Parse filter rules
+ if (!ParseFilterRules(config)) {
+ m_is_valid = false;
+ return;
+ }
+
+ // Everything worked.
+ m_is_valid = true;
+ }
+
+ bool ParseSourceFlags(const JSONObject &config) {
+ // Get the source-flags dictionary.
+ auto source_flags_sp = config.GetObject("source-flags");
+ if (!source_flags_sp)
+ return false;
+ if (!JSONObject::classof(source_flags_sp.get()))
+ return false;
+
+ const JSONObject &source_flags =
+ *static_cast<JSONObject *>(source_flags_sp.get());
+
+ // Parse out the flags.
+ bool include_any_process = false;
+ bool include_callstacks = false;
+ bool include_info_level = false;
+ bool include_debug_level = false;
+ bool live_stream = false;
+
+ if (!source_flags.GetObjectAsBool("any-process", include_any_process)) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'any-process' missing from "
+ "configuration.");
+ return false;
+ }
+ if (!source_flags.GetObjectAsBool("callstacks", include_callstacks)) {
+ // We currently suppress the availability of this on the lldb
+ // side. We include here for devices when we enable in the
+ // future.
+ // DNBLogThreadedIf(LOG_DARWIN_LOG,
+ // "Source-flag 'callstacks' missing from "
+ // "configuration.");
+
+ // OK. We just skip callstacks.
+ // return false;
+ }
+ if (!source_flags.GetObjectAsBool("info-level", include_info_level)) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'info-level' missing from "
+ "configuration.");
+ return false;
+ }
+ if (!source_flags.GetObjectAsBool("debug-level", include_debug_level)) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'debug-level' missing from "
+ "configuration.");
+ return false;
+ }
+ if (!source_flags.GetObjectAsBool("live-stream", live_stream)) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'live-stream' missing from "
+ "configuration.");
+ return false;
+ }
+
+ // Setup the SPI flags based on this.
+ m_activity_stream_flags = 0;
+ if (!include_any_process)
+ m_activity_stream_flags |= OS_ACTIVITY_STREAM_PROCESS_ONLY;
+ if (include_callstacks)
+ m_activity_stream_flags |= OS_ACTIVITY_STREAM_CALLSTACK;
+ if (include_info_level)
+ m_activity_stream_flags |= OS_ACTIVITY_STREAM_INFO;
+ if (include_debug_level)
+ m_activity_stream_flags |= OS_ACTIVITY_STREAM_DEBUG;
+ if (!live_stream)
+ m_activity_stream_flags |= OS_ACTIVITY_STREAM_BUFFERED;
- static FilterTarget
- TargetStringToEnum(const std::string &filter_target_name)
- {
- if (filter_target_name == "activity")
- return eFilterTargetActivity;
- else if (filter_target_name == "activity-chain")
- return eFilterTargetActivityChain;
- else if (filter_target_name == "category")
- return eFilterTargetCategory;
- else if (filter_target_name == "message")
- return eFilterTargetMessage;
- else if (filter_target_name == "subsystem")
- return eFilterTargetSubsystem;
- else
- return eFilterTargetInvalid;
- }
-
- class Configuration
- {
- public:
-
- Configuration(const JSONObject &config) :
- m_is_valid(false),
- m_activity_stream_flags(OS_ACTIVITY_STREAM_PROCESS_ONLY),
- m_filter_chain_sp(nullptr)
- {
- // Parse out activity stream flags
- if (!ParseSourceFlags(config))
- {
- m_is_valid = false;
- return;
- }
-
- // Parse filter rules
- if (!ParseFilterRules(config))
- {
- m_is_valid = false;
- return;
- }
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "m_activity_stream_flags = 0x%03x",
+ m_activity_stream_flags);
- // Everything worked.
- m_is_valid = true;
- }
-
- bool
- ParseSourceFlags(const JSONObject &config)
- {
- // Get the source-flags dictionary.
- auto source_flags_sp = config.GetObject("source-flags");
- if (!source_flags_sp)
- return false;
- if (!JSONObject::classof(source_flags_sp.get()))
- return false;
-
- const JSONObject &source_flags =
- *static_cast<JSONObject*>(source_flags_sp.get());
-
- // Parse out the flags.
- bool include_any_process = false;
- bool include_callstacks = false;
- bool include_info_level = false;
- bool include_debug_level = false;
- bool live_stream = false;
-
- if (!source_flags.GetObjectAsBool("any-process",
- include_any_process))
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "Source-flag 'any-process' missing from "
- "configuration.");
- return false;
- }
- if (!source_flags.GetObjectAsBool("callstacks",
- include_callstacks))
- {
- // We currently suppress the availability of this on the lldb
- // side. We include here for devices when we enable in the
- // future.
- // DNBLogThreadedIf(LOG_DARWIN_LOG,
- // "Source-flag 'callstacks' missing from "
- // "configuration.");
-
- // OK. We just skip callstacks.
- // return false;
- }
- if (!source_flags.GetObjectAsBool("info-level",
- include_info_level))
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "Source-flag 'info-level' missing from "
- "configuration.");
- return false;
- }
- if (!source_flags.GetObjectAsBool("debug-level",
- include_debug_level))
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "Source-flag 'debug-level' missing from "
- "configuration.");
- return false;
- }
- if (!source_flags.GetObjectAsBool("live-stream",
- live_stream))
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "Source-flag 'live-stream' missing from "
- "configuration.");
- return false;
- }
-
- // Setup the SPI flags based on this.
- m_activity_stream_flags = 0;
- if (!include_any_process)
- m_activity_stream_flags |= OS_ACTIVITY_STREAM_PROCESS_ONLY;
- if (include_callstacks)
- m_activity_stream_flags |= OS_ACTIVITY_STREAM_CALLSTACK;
- if (include_info_level)
- m_activity_stream_flags |= OS_ACTIVITY_STREAM_INFO;
- if (include_debug_level)
- m_activity_stream_flags |= OS_ACTIVITY_STREAM_DEBUG;
- if (!live_stream)
- m_activity_stream_flags |= OS_ACTIVITY_STREAM_BUFFERED;
+ return true;
+ }
- DNBLogThreadedIf(LOG_DARWIN_LOG, "m_activity_stream_flags = 0x%03x",
- m_activity_stream_flags);
+ bool ParseFilterRules(const JSONObject &config) {
+ // Retrieve the default rule.
+ bool filter_default_accept = true;
+ if (!config.GetObjectAsBool("filter-fall-through-accepts",
+ filter_default_accept)) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Setting 'filter-fall-through-accepts' "
+ "missing from configuration.");
+ return false;
+ }
+ m_filter_chain_sp.reset(new LogFilterChain(filter_default_accept));
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLog no-match rule: %s.",
+ filter_default_accept ? "accept" : "reject");
+
+ // If we don't have the filter-rules array, we're done.
+ auto filter_rules_sp = config.GetObject("filter-rules");
+ if (!filter_rules_sp) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "No 'filter-rules' config element, all log "
+ "entries will use the no-match action (%s).",
+ filter_default_accept ? "accept" : "reject");
+ return true;
+ }
+ if (!JSONArray::classof(filter_rules_sp.get()))
+ return false;
+ const JSONArray &rules_config =
+ *static_cast<JSONArray *>(filter_rules_sp.get());
+
+ // Create the filters.
+ for (auto &rule_sp : rules_config.m_elements) {
+ if (!JSONObject::classof(rule_sp.get()))
+ return false;
+ const JSONObject &rule_config = *static_cast<JSONObject *>(rule_sp.get());
- return true;
- }
+ // Get whether this filter accepts or rejects.
+ bool filter_accepts = true;
+ if (!rule_config.GetObjectAsBool("accept", filter_accepts)) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter 'accept' element missing.");
+ return false;
+ }
- bool
- ParseFilterRules(const JSONObject &config)
- {
- // Retrieve the default rule.
- bool filter_default_accept = true;
- if (!config.GetObjectAsBool("filter-fall-through-accepts",
- filter_default_accept))
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "Setting 'filter-fall-through-accepts' "
- "missing from configuration.");
- return false;
- }
- m_filter_chain_sp.reset(new LogFilterChain(filter_default_accept));
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "DarwinLog no-match rule: %s.",
- filter_default_accept ? "accept" : "reject");
-
- // If we don't have the filter-rules array, we're done.
- auto filter_rules_sp = config.GetObject("filter-rules");
- if (!filter_rules_sp)
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "No 'filter-rules' config element, all log "
- "entries will use the no-match action (%s).",
- filter_default_accept ? "accept" : "reject");
- return true;
- }
- if (!JSONArray::classof(filter_rules_sp.get()))
- return false;
- const JSONArray &rules_config =
- *static_cast<JSONArray*>(filter_rules_sp.get());
-
- // Create the filters.
- for (auto &rule_sp : rules_config.m_elements)
- {
- if (!JSONObject::classof(rule_sp.get()))
- return false;
- const JSONObject &rule_config = *static_cast<JSONObject*>
- (rule_sp.get());
-
- // Get whether this filter accepts or rejects.
- bool filter_accepts = true;
- if (!rule_config.GetObjectAsBool("accept", filter_accepts))
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "Filter 'accept' element missing.");
- return false;
- }
-
- // Grab the target log field attribute for the match.
- std::string target_attribute;
- if (!rule_config.GetObjectAsString("attribute",
- target_attribute))
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "Filter 'attribute' element missing.");
- return false;
- }
- auto target_enum = TargetStringToEnum(target_attribute);
- if (target_enum == eFilterTargetInvalid)
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "Filter attribute '%s' unsupported.",
- target_attribute.c_str());
- return false;
- }
-
- // Handle operation-specific fields and filter creation.
- std::string filter_type;
- if (!rule_config.GetObjectAsString("type", filter_type))
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "Filter 'type' element missing.");
- return false;
- }
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "Reading filter of type '%s'", filter_type
- .c_str());
-
- LogFilterSP filter_sp;
- if (filter_type == "regex")
- {
- // Grab the regex for the match.
- std::string regex;
- if (!rule_config.GetObjectAsString("regex",
- regex))
- {
- DNBLogError("Regex filter missing 'regex' element.");
- return false;
- }
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "regex for filter: \"%s\"", regex.c_str());
-
- // Create the regex filter.
- auto regex_filter =
- new LogFilterRegex(filter_accepts, target_enum, regex);
- filter_sp.reset(regex_filter);
-
- // Validate that the filter is okay.
- if (!regex_filter->IsValid())
- {
- DNBLogError("Invalid regex in filter: "
- "regex=\"%s\", error=%s",
- regex.c_str(),
- regex_filter->GetErrorAsCString());
- return false;
- }
- }
- else if (filter_type == "match")
- {
- // Grab the regex for the match.
- std::string exact_text;
- if (!rule_config.GetObjectAsString("exact_text",
- exact_text))
- {
- DNBLogError("Exact match filter missing "
- "'exact_text' element.");
- return false;
- }
-
- // Create the filter.
- filter_sp.reset(new LogFilterExactMatch(filter_accepts,
- target_enum,
- exact_text));
- }
-
- // Add the filter to the chain.
- m_filter_chain_sp->AppendFilter(filter_sp);
- }
- return true;
- }
+ // Grab the target log field attribute for the match.
+ std::string target_attribute;
+ if (!rule_config.GetObjectAsString("attribute", target_attribute)) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter 'attribute' element missing.");
+ return false;
+ }
+ auto target_enum = TargetStringToEnum(target_attribute);
+ if (target_enum == eFilterTargetInvalid) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter attribute '%s' unsupported.",
+ target_attribute.c_str());
+ return false;
+ }
- bool
- IsValid() const
- {
- return m_is_valid;
+ // Handle operation-specific fields and filter creation.
+ std::string filter_type;
+ if (!rule_config.GetObjectAsString("type", filter_type)) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter 'type' element missing.");
+ return false;
+ }
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "Reading filter of type '%s'",
+ filter_type.c_str());
+
+ LogFilterSP filter_sp;
+ if (filter_type == "regex") {
+ // Grab the regex for the match.
+ std::string regex;
+ if (!rule_config.GetObjectAsString("regex", regex)) {
+ DNBLogError("Regex filter missing 'regex' element.");
+ return false;
}
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "regex for filter: \"%s\"",
+ regex.c_str());
- os_activity_stream_flag_t
- GetActivityStreamFlags() const
- {
- return m_activity_stream_flags;
+ // Create the regex filter.
+ auto regex_filter =
+ new LogFilterRegex(filter_accepts, target_enum, regex);
+ filter_sp.reset(regex_filter);
+
+ // Validate that the filter is okay.
+ if (!regex_filter->IsValid()) {
+ DNBLogError("Invalid regex in filter: "
+ "regex=\"%s\", error=%s",
+ regex.c_str(), regex_filter->GetErrorAsCString());
+ return false;
}
-
- const LogFilterChainSP &
- GetLogFilterChain() const
- {
- return m_filter_chain_sp;
+ } else if (filter_type == "match") {
+ // Grab the regex for the match.
+ std::string exact_text;
+ if (!rule_config.GetObjectAsString("exact_text", exact_text)) {
+ DNBLogError("Exact match filter missing "
+ "'exact_text' element.");
+ return false;
}
- private:
+ // Create the filter.
+ filter_sp.reset(
+ new LogFilterExactMatch(filter_accepts, target_enum, exact_text));
+ }
- bool m_is_valid;
- os_activity_stream_flag_t m_activity_stream_flags;
- LogFilterChainSP m_filter_chain_sp;
-
- };
-}
-
-bool
-DarwinLogCollector::IsSupported()
-{
- // We're supported if we have successfully looked up the SPI entry points.
- return LookupSPICalls();
-}
-
-bool
-DarwinLogCollector::StartCollectingForProcess(nub_process_t pid,
- const JSONObject &config)
-{
- // If we're currently collecting for this process, kill the existing
- // collector.
- if (CancelStreamForProcess(pid))
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "%s() killed existing DarwinLog collector for pid %d.",
- __FUNCTION__, pid);
- }
-
- // If the process isn't alive, we're done.
- if (!DNBProcessIsAlive(pid))
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "%s() cannot collect for pid %d: process not alive.",
- __FUNCTION__, pid);
- return false;
+ // Add the filter to the chain.
+ m_filter_chain_sp->AppendFilter(filter_sp);
}
+ return true;
+ }
- // Validate the configuration.
- auto spi_config = Configuration(config);
- if (!spi_config.IsValid())
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG,
- "%s() invalid configuration, will not enable log "
- "collection", __FUNCTION__);
- return false;
- }
+ bool IsValid() const { return m_is_valid; }
- // Create the stream collector that will manage collected data
- // for this pid.
- DarwinLogCollectorSP collector_sp(new DarwinLogCollector(pid,
- spi_config.GetLogFilterChain()));
- std::weak_ptr<DarwinLogCollector> collector_wp(collector_sp);
-
- // Setup the stream handling block.
- os_activity_stream_block_t block = ^bool (os_activity_stream_entry_t entry,
- int error) {
+ os_activity_stream_flag_t GetActivityStreamFlags() const {
+ return m_activity_stream_flags;
+ }
+
+ const LogFilterChainSP &GetLogFilterChain() const {
+ return m_filter_chain_sp;
+ }
+
+private:
+ bool m_is_valid;
+ os_activity_stream_flag_t m_activity_stream_flags;
+ LogFilterChainSP m_filter_chain_sp;
+};
+}
+
+bool DarwinLogCollector::IsSupported() {
+ // We're supported if we have successfully looked up the SPI entry points.
+ return LookupSPICalls();
+}
+
+bool DarwinLogCollector::StartCollectingForProcess(nub_process_t pid,
+ const JSONObject &config) {
+ // If we're currently collecting for this process, kill the existing
+ // collector.
+ if (CancelStreamForProcess(pid)) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "%s() killed existing DarwinLog collector for pid %d.",
+ __FUNCTION__, pid);
+ }
+
+ // If the process isn't alive, we're done.
+ if (!DNBProcessIsAlive(pid)) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "%s() cannot collect for pid %d: process not alive.",
+ __FUNCTION__, pid);
+ return false;
+ }
+
+ // Validate the configuration.
+ auto spi_config = Configuration(config);
+ if (!spi_config.IsValid()) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "%s() invalid configuration, will not enable log "
+ "collection",
+ __FUNCTION__);
+ return false;
+ }
+
+ // Create the stream collector that will manage collected data
+ // for this pid.
+ DarwinLogCollectorSP collector_sp(
+ new DarwinLogCollector(pid, spi_config.GetLogFilterChain()));
+ std::weak_ptr<DarwinLogCollector> collector_wp(collector_sp);
+
+ // Setup the stream handling block.
+ os_activity_stream_block_t block =
+ ^bool(os_activity_stream_entry_t entry, int error) {
// Check if our collector is still alive.
DarwinLogCollectorSP inner_collector_sp = collector_wp.lock();
if (!inner_collector_sp)
- return false;
+ return false;
return inner_collector_sp->HandleStreamEntry(entry, error);
- };
+ };
- os_activity_stream_event_block_t stream_event_block =
- ^void (os_activity_stream_t stream, os_activity_stream_event_t event) {
- switch (event)
- {
- case OS_ACTIVITY_STREAM_EVENT_STARTED:
- DNBLogThreadedIf(LOG_DARWIN_LOG, "received stream event: "
- "OS_ACTIVITY_STREAM_EVENT_STARTED, stream %p.",
- (void*)stream);
- break;
- case OS_ACTIVITY_STREAM_EVENT_STOPPED:
- DNBLogThreadedIf(LOG_DARWIN_LOG, "received stream event: "
- "OS_ACTIVITY_STREAM_EVENT_STOPPED, stream %p.",
- (void*)stream);
- break;
- case OS_ACTIVITY_STREAM_EVENT_FAILED:
- DNBLogThreadedIf(LOG_DARWIN_LOG, "received stream event: "
- "OS_ACTIVITY_STREAM_EVENT_FAILED, stream %p.",
- (void*)stream);
- break;
- case OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED:
- DNBLogThreadedIf(LOG_DARWIN_LOG, "received stream event: "
- "OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED, stream %p.",
- (void*)stream);
- break;
- case OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED:
- DNBLogThreadedIf(LOG_DARWIN_LOG, "received stream event: "
- "OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED, stream %p.",
- (void*)stream);
- break;
- }
- };
-
- // Create the stream.
- os_activity_stream_t activity_stream =
- (*s_os_activity_stream_for_pid)(pid,
- spi_config.GetActivityStreamFlags(),
- block);
- collector_sp->SetActivityStream(activity_stream);
-
- // Specify the stream-related event handler.
- (*s_os_activity_stream_set_event_handler)(
- activity_stream, stream_event_block);
+ os_activity_stream_event_block_t stream_event_block = ^void(
+ os_activity_stream_t stream, os_activity_stream_event_t event) {
+ switch (event) {
+ case OS_ACTIVITY_STREAM_EVENT_STARTED:
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "received stream event: "
+ "OS_ACTIVITY_STREAM_EVENT_STARTED, stream %p.",
+ (void *)stream);
+ break;
+ case OS_ACTIVITY_STREAM_EVENT_STOPPED:
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "received stream event: "
+ "OS_ACTIVITY_STREAM_EVENT_STOPPED, stream %p.",
+ (void *)stream);
+ break;
+ case OS_ACTIVITY_STREAM_EVENT_FAILED:
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "received stream event: "
+ "OS_ACTIVITY_STREAM_EVENT_FAILED, stream %p.",
+ (void *)stream);
+ break;
+ case OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED:
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "received stream event: "
+ "OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED, stream %p.",
+ (void *)stream);
+ break;
+ case OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED:
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "received stream event: "
+ "OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED, stream %p.",
+ (void *)stream);
+ break;
+ }
+ };
+
+ // Create the stream.
+ os_activity_stream_t activity_stream = (*s_os_activity_stream_for_pid)(
+ pid, spi_config.GetActivityStreamFlags(), block);
+ collector_sp->SetActivityStream(activity_stream);
+
+ // Specify the stream-related event handler.
+ (*s_os_activity_stream_set_event_handler)(activity_stream,
+ stream_event_block);
- // Start the stream.
- (*s_os_activity_stream_resume)(activity_stream);
+ // Start the stream.
+ (*s_os_activity_stream_resume)(activity_stream);
- TrackCollector(collector_sp);
- return true;
+ TrackCollector(collector_sp);
+ return true;
}
DarwinLogEventVector
-DarwinLogCollector::GetEventsForProcess(nub_process_t pid)
-{
- auto collector_sp = FindCollectorForProcess(pid);
- if (!collector_sp)
- {
- // We're not tracking a stream for this process.
- return DarwinLogEventVector();
- }
-
- return collector_sp->RemoveEvents();
-}
-
-bool
-DarwinLogCollector::CancelStreamForProcess(nub_process_t pid)
-{
- auto collector_sp = FindCollectorForProcess(pid);
- if (!collector_sp)
- {
- // We're not tracking a stream for this process.
- return false;
- }
-
- collector_sp->CancelActivityStream();
- StopTrackingCollector(collector_sp);
-
- return true;
-}
-
-const char*
-DarwinLogCollector::GetActivityForID(os_activity_id_t activity_id) const
-{
- auto find_it = m_activity_map.find(activity_id);
- return (find_it != m_activity_map.end()) ?
- find_it->second.m_name.c_str() :
- nullptr;
+DarwinLogCollector::GetEventsForProcess(nub_process_t pid) {
+ auto collector_sp = FindCollectorForProcess(pid);
+ if (!collector_sp) {
+ // We're not tracking a stream for this process.
+ return DarwinLogEventVector();
+ }
+
+ return collector_sp->RemoveEvents();
+}
+
+bool DarwinLogCollector::CancelStreamForProcess(nub_process_t pid) {
+ auto collector_sp = FindCollectorForProcess(pid);
+ if (!collector_sp) {
+ // We're not tracking a stream for this process.
+ return false;
+ }
+
+ collector_sp->CancelActivityStream();
+ StopTrackingCollector(collector_sp);
+
+ return true;
+}
+
+const char *
+DarwinLogCollector::GetActivityForID(os_activity_id_t activity_id) const {
+ auto find_it = m_activity_map.find(activity_id);
+ return (find_it != m_activity_map.end()) ? find_it->second.m_name.c_str()
+ : nullptr;
}
/// Retrieve the full parent-child chain for activity names. These
/// can be arbitrarily deep. This method assumes the caller has already
/// locked the activity mutex.
-void
-DarwinLogCollector::GetActivityChainForID_internal(os_activity_id_t activity_id,
- std::string &result,
- size_t depth) const
-{
- if (depth > MAX_ACTIVITY_CHAIN_DEPTH)
- {
- // Terminating condition - too deeply nested.
- return;
- }
- else if (activity_id == 0)
- {
- // Terminating condition - no activity.
- return;
- }
-
- auto find_it = m_activity_map.find(activity_id);
- if (find_it == m_activity_map.end())
- {
- //Terminating condition - no data for activity_id.
- return;
- }
-
- // Activity name becomes parent activity name chain + ':' + our activity
- // name.
- GetActivityChainForID_internal(find_it->second.m_parent_id, result,
- depth + 1);
- if (!result.empty())
- result += ':';
- result += find_it->second.m_name;
+void DarwinLogCollector::GetActivityChainForID_internal(
+ os_activity_id_t activity_id, std::string &result, size_t depth) const {
+ if (depth > MAX_ACTIVITY_CHAIN_DEPTH) {
+ // Terminating condition - too deeply nested.
+ return;
+ } else if (activity_id == 0) {
+ // Terminating condition - no activity.
+ return;
+ }
+
+ auto find_it = m_activity_map.find(activity_id);
+ if (find_it == m_activity_map.end()) {
+ // Terminating condition - no data for activity_id.
+ return;
+ }
+
+ // Activity name becomes parent activity name chain + ':' + our activity
+ // name.
+ GetActivityChainForID_internal(find_it->second.m_parent_id, result,
+ depth + 1);
+ if (!result.empty())
+ result += ':';
+ result += find_it->second.m_name;
}
std::string
-DarwinLogCollector::GetActivityChainForID(os_activity_id_t activity_id) const
-{
- std::string result;
- {
- std::lock_guard<std::mutex> locker(m_activity_info_mutex);
- GetActivityChainForID_internal(activity_id, result, 1);
- }
- return result;
+DarwinLogCollector::GetActivityChainForID(os_activity_id_t activity_id) const {
+ std::string result;
+ {
+ std::lock_guard<std::mutex> locker(m_activity_info_mutex);
+ GetActivityChainForID_internal(activity_id, result, 1);
+ }
+ return result;
}
DarwinLogCollector::DarwinLogCollector(nub_process_t pid,
- const LogFilterChainSP &filter_chain_sp):
- ActivityStore(),
- m_pid(pid),
- m_activity_stream(0),
- m_events(),
- m_events_mutex(),
- m_filter_chain_sp(filter_chain_sp),
- m_activity_info_mutex(),
- m_activity_map()
-{
-}
-
-DarwinLogCollector::~DarwinLogCollector()
-{
- // Cancel the stream.
- if (m_activity_stream)
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG, "tearing down activity stream "
- "collector for %d", m_pid);
- (*s_os_activity_stream_cancel)(m_activity_stream);
- m_activity_stream = 0;
- }
- else
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG, "no stream to tear down for %d",
- m_pid);
- }
-}
+ const LogFilterChainSP &filter_chain_sp)
+ : ActivityStore(), m_pid(pid), m_activity_stream(0), m_events(),
+ m_events_mutex(), m_filter_chain_sp(filter_chain_sp),
+ m_activity_info_mutex(), m_activity_map() {}
+
+DarwinLogCollector::~DarwinLogCollector() {
+ // Cancel the stream.
+ if (m_activity_stream) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "tearing down activity stream "
+ "collector for %d",
+ m_pid);
+ (*s_os_activity_stream_cancel)(m_activity_stream);
+ m_activity_stream = 0;
+ } else {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "no stream to tear down for %d", m_pid);
+ }
+}
+
+void DarwinLogCollector::SignalDataAvailable() {
+ RNBRemoteSP remoteSP(g_remoteSP);
+ if (!remoteSP) {
+ // We're done. This is unexpected.
+ StopTrackingCollector(shared_from_this());
+ return;
+ }
+
+ RNBContext &ctx = remoteSP->Context();
+ ctx.Events().SetEvents(RNBContext::event_darwin_log_data_available);
+ // Wait for the main thread to consume this notification if it requested
+ // we wait for it.
+ ctx.Events().WaitForResetAck(RNBContext::event_darwin_log_data_available);
+}
+
+void DarwinLogCollector::SetActivityStream(
+ os_activity_stream_t activity_stream) {
+ m_activity_stream = activity_stream;
+}
+
+bool DarwinLogCollector::HandleStreamEntry(os_activity_stream_entry_t entry,
+ int error) {
+ if ((error == 0) && (entry != nullptr)) {
+ if (entry->pid != m_pid) {
+ // For now, skip messages not originating from our process.
+ // Later we might want to keep all messages related to an event
+ // that we're tracking, even when it came from another process,
+ // possibly doing work on our behalf.
+ return true;
+ }
+
+ switch (entry->type) {
+ case OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE:
+ DNBLogThreadedIf(
+ LOG_DARWIN_LOG, "received activity create: "
+ "%s, creator aid %" PRIu64 ", unique_pid %" PRIu64
+ "(activity id=%" PRIu64 ", parent id=%" PRIu64 ")",
+ entry->activity_create.name, entry->activity_create.creator_aid,
+ entry->activity_create.unique_pid, entry->activity_id,
+ entry->parent_id);
+ {
+ std::lock_guard<std::mutex> locker(m_activity_info_mutex);
+ m_activity_map.insert(
+ std::make_pair(entry->activity_id,
+ ActivityInfo(entry->activity_create.name,
+ entry->activity_id, entry->parent_id)));
+ }
+ break;
+
+ case OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION:
+ DNBLogThreadedIf(
+ LOG_DARWIN_LOG, "received activity transition:"
+ "new aid: %" PRIu64 "(activity id=%" PRIu64
+ ", parent id=%" PRIu64 ", tid %" PRIu64 ")",
+ entry->activity_transition.transition_id, entry->activity_id,
+ entry->parent_id, entry->activity_transition.thread);
+ break;
+
+ case OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE: {
+ DNBLogThreadedIf(
+ LOG_DARWIN_LOG, "received log message: "
+ "(activity id=%" PRIu64 ", parent id=%" PRIu64 ", "
+ "tid %" PRIu64 "): format %s",
+ entry->activity_id, entry->parent_id, entry->log_message.thread,
+ entry->log_message.format ? entry->log_message.format
+ : "<invalid-format>");
+
+ // Do the real work here.
+ {
+ // Ensure our process is still alive. If not, we can
+ // cancel the collection.
+ if (!DNBProcessIsAlive(m_pid)) {
+ // We're outta here. This is the manner in which we
+ // stop collecting for a process.
+ StopTrackingCollector(shared_from_this());
+ return false;
+ }
-void
-DarwinLogCollector::SignalDataAvailable()
-{
- RNBRemoteSP remoteSP(g_remoteSP);
- if (!remoteSP)
- {
- // We're done. This is unexpected.
- StopTrackingCollector(shared_from_this());
- return;
- }
-
- RNBContext& ctx = remoteSP->Context();
- ctx.Events().SetEvents(RNBContext::event_darwin_log_data_available);
- // Wait for the main thread to consume this notification if it requested
- // we wait for it.
- ctx.Events().WaitForResetAck(RNBContext::event_darwin_log_data_available);
-}
-
-void
-DarwinLogCollector::SetActivityStream(os_activity_stream_t activity_stream)
-{
- m_activity_stream = activity_stream;
-}
-
-bool
-DarwinLogCollector::HandleStreamEntry(os_activity_stream_entry_t entry,
- int error)
-{
- if ((error == 0) && (entry != nullptr))
- {
- if (entry->pid != m_pid)
- {
- // For now, skip messages not originating from our process.
- // Later we might want to keep all messages related to an event
- // that we're tracking, even when it came from another process,
- // possibly doing work on our behalf.
- return true;
+ LogMessageOsLog os_log_message(*this, *entry);
+ if (!m_filter_chain_sp ||
+ !m_filter_chain_sp->GetAcceptMessage(os_log_message)) {
+ // This log message was rejected by the filter,
+ // so stop processing it now.
+ return true;
}
- switch (entry->type)
- {
- case OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE:
- DNBLogThreadedIf(LOG_DARWIN_LOG, "received activity create: "
- "%s, creator aid %" PRIu64 ", unique_pid %" PRIu64
- "(activity id=%" PRIu64 ", parent id=%" PRIu64 ")",
- entry->activity_create.name,
- entry->activity_create.creator_aid,
- entry->activity_create.unique_pid, entry->activity_id,
- entry->parent_id
- );
- {
- std::lock_guard<std::mutex> locker(m_activity_info_mutex);
- m_activity_map.insert(std::make_pair(
- entry->activity_id,
- ActivityInfo(
- entry->activity_create.name,
- entry->activity_id,
- entry->parent_id)));
- }
- break;
-
- case OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION:
- DNBLogThreadedIf(LOG_DARWIN_LOG, "received activity transition:"
- "new aid: %" PRIu64 "(activity id=%" PRIu64
- ", parent id=%" PRIu64 ", tid %" PRIu64 ")",
- entry->activity_transition.transition_id,
- entry->activity_id, entry->parent_id,
- entry->activity_transition.thread);
- break;
-
- case OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE:
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG, "received log message: "
- "(activity id=%" PRIu64 ", parent id=%" PRIu64 ", "
- "tid %" PRIu64 "): format %s",
- entry->activity_id, entry->parent_id,
- entry->log_message.thread,
- entry->log_message.format ? entry->log_message.format :
- "<invalid-format>");
-
- // Do the real work here.
- {
- // Ensure our process is still alive. If not, we can
- // cancel the collection.
- if (!DNBProcessIsAlive(m_pid))
- {
- // We're outta here. This is the manner in which we
- // stop collecting for a process.
- StopTrackingCollector(shared_from_this());
- return false;
- }
-
- LogMessageOsLog os_log_message(*this, *entry);
- if (!m_filter_chain_sp ||
- !m_filter_chain_sp->GetAcceptMessage(os_log_message))
- {
- // This log message was rejected by the filter,
- // so stop processing it now.
- return true;
- }
-
- // Copy over the relevant bits from the message.
- const struct os_log_message_s &log_message =
- entry->log_message;
-
- DarwinLogEventSP message_sp(new DarwinLogEvent());
- // Indicate this event is a log message event.
- message_sp->AddStringItem("type", "log");
-
- // Add the message contents (fully expanded).
- // Consider expanding on the remote side.
- // Then we don't pay for expansion until when it is
- // used.
- const char *message_text = os_log_message.GetMessage();
- if (message_text)
- message_sp->AddStringItem("message", message_text);
-
- // Add some useful data fields.
- message_sp->AddIntegerItem("timestamp",
- log_message.timestamp);
-
- // Do we want to do all activity name resolution on this
- // side? Maybe. For now, send IDs and ID->name mappings
- // and fix this up on that side. Later, when we add
- // debugserver-side filtering, we'll want to get the
- // activity names over here, so we should probably
- // just send them as resolved strings.
- message_sp->AddIntegerItem("activity_id",
- entry->activity_id);
- message_sp->AddIntegerItem("parent_id",
- entry->parent_id);
- message_sp->AddIntegerItem("thread_id",
- log_message.thread);
- if (log_message.subsystem && strlen(log_message.subsystem)
- > 0)
- message_sp->AddStringItem("subsystem",
- log_message.subsystem);
- if (log_message.category && strlen(log_message.category)
- > 0)
- message_sp->AddStringItem("category",
- log_message.category);
- if (entry->activity_id != 0)
- {
- std::string activity_chain =
- GetActivityChainForID(entry->activity_id);
- if (!activity_chain.empty())
- message_sp->AddStringItem("activity-chain",
- activity_chain);
- }
-
- // Add it to the list for later collection.
- {
- std::lock_guard<std::mutex> locker(m_events_mutex);
- m_events.push_back(message_sp);
- }
- SignalDataAvailable();
- }
- break;
- }
+ // Copy over the relevant bits from the message.
+ const struct os_log_message_s &log_message = entry->log_message;
+
+ DarwinLogEventSP message_sp(new DarwinLogEvent());
+ // Indicate this event is a log message event.
+ message_sp->AddStringItem("type", "log");
+
+ // Add the message contents (fully expanded).
+ // Consider expanding on the remote side.
+ // Then we don't pay for expansion until when it is
+ // used.
+ const char *message_text = os_log_message.GetMessage();
+ if (message_text)
+ message_sp->AddStringItem("message", message_text);
+
+ // Add some useful data fields.
+ message_sp->AddIntegerItem("timestamp", log_message.timestamp);
+
+ // Do we want to do all activity name resolution on this
+ // side? Maybe. For now, send IDs and ID->name mappings
+ // and fix this up on that side. Later, when we add
+ // debugserver-side filtering, we'll want to get the
+ // activity names over here, so we should probably
+ // just send them as resolved strings.
+ message_sp->AddIntegerItem("activity_id", entry->activity_id);
+ message_sp->AddIntegerItem("parent_id", entry->parent_id);
+ message_sp->AddIntegerItem("thread_id", log_message.thread);
+ if (log_message.subsystem && strlen(log_message.subsystem) > 0)
+ message_sp->AddStringItem("subsystem", log_message.subsystem);
+ if (log_message.category && strlen(log_message.category) > 0)
+ message_sp->AddStringItem("category", log_message.category);
+ if (entry->activity_id != 0) {
+ std::string activity_chain =
+ GetActivityChainForID(entry->activity_id);
+ if (!activity_chain.empty())
+ message_sp->AddStringItem("activity-chain", activity_chain);
}
- }
- else
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG, "HandleStreamEntry: final call, "
- "error %d", error);
- }
- return true;
-}
-DarwinLogEventVector
-DarwinLogCollector::RemoveEvents()
-{
- DarwinLogEventVector returned_events;
- {
- std::lock_guard<std::mutex> locker(m_events_mutex);
- returned_events.swap(m_events);
- }
- DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLogCollector::%s(): removing %lu "
- "queued log entries", __FUNCTION__,
- returned_events.size());
- return returned_events;
-}
-
-void
-DarwinLogCollector::CancelActivityStream()
-{
- if (!m_activity_stream)
- return;
-
- DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLogCollector::%s(): canceling "
- "activity stream %p", __FUNCTION__,
- m_activity_stream);
- (*s_os_activity_stream_cancel)(m_activity_stream);
- m_activity_stream = nullptr;
+ // Add it to the list for later collection.
+ {
+ std::lock_guard<std::mutex> locker(m_events_mutex);
+ m_events.push_back(message_sp);
+ }
+ SignalDataAvailable();
+ }
+ break;
+ }
+ }
+ } else {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "HandleStreamEntry: final call, "
+ "error %d",
+ error);
+ }
+ return true;
+}
+
+DarwinLogEventVector DarwinLogCollector::RemoveEvents() {
+ DarwinLogEventVector returned_events;
+ {
+ std::lock_guard<std::mutex> locker(m_events_mutex);
+ returned_events.swap(m_events);
+ }
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLogCollector::%s(): removing %lu "
+ "queued log entries",
+ __FUNCTION__, returned_events.size());
+ return returned_events;
+}
+
+void DarwinLogCollector::CancelActivityStream() {
+ if (!m_activity_stream)
+ return;
+
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLogCollector::%s(): canceling "
+ "activity stream %p",
+ __FUNCTION__, m_activity_stream);
+ (*s_os_activity_stream_cancel)(m_activity_stream);
+ m_activity_stream = nullptr;
}
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h Tue Sep 6 15:57:50 2016
@@ -18,122 +18,97 @@
#include "ActivityStore.h"
#include "ActivityStreamSPI.h"
+#include "DNBDefs.h"
#include "DarwinLogEvent.h"
#include "DarwinLogInterfaces.h"
-#include "DNBDefs.h"
#include "JSON.h"
class DarwinLogCollector;
typedef std::shared_ptr<DarwinLogCollector> DarwinLogCollectorSP;
-class DarwinLogCollector:
- public std::enable_shared_from_this<DarwinLogCollector>,
- public ActivityStore
-{
+class DarwinLogCollector
+ : public std::enable_shared_from_this<DarwinLogCollector>,
+ public ActivityStore {
public:
+ //------------------------------------------------------------------
+ /// Return whether the os_log and activity tracing SPI is available.
+ ///
+ /// @return \b true if the activity stream support is available,
+ /// \b false otherwise.
+ //------------------------------------------------------------------
+ static bool IsSupported();
+
+ //------------------------------------------------------------------
+ /// Return a log function suitable for DNBLog to use as the internal
+ /// logging function.
+ ///
+ /// @return a DNBLog-style logging function if IsSupported() returns
+ /// true; otherwise, returns nullptr.
+ //------------------------------------------------------------------
+ static DNBCallbackLog GetLogFunction();
+
+ static bool StartCollectingForProcess(nub_process_t pid,
+ const JSONObject &config);
+
+ static bool CancelStreamForProcess(nub_process_t pid);
+
+ static DarwinLogEventVector GetEventsForProcess(nub_process_t pid);
+
+ ~DarwinLogCollector();
+
+ pid_t GetProcessID() const { return m_pid; }
+
+ //------------------------------------------------------------------
+ // ActivityStore API
+ //------------------------------------------------------------------
+ const char *GetActivityForID(os_activity_id_t activity_id) const override;
- //------------------------------------------------------------------
- /// Return whether the os_log and activity tracing SPI is available.
- ///
- /// @return \b true if the activity stream support is available,
- /// \b false otherwise.
- //------------------------------------------------------------------
- static bool
- IsSupported();
-
- //------------------------------------------------------------------
- /// Return a log function suitable for DNBLog to use as the internal
- /// logging function.
- ///
- /// @return a DNBLog-style logging function if IsSupported() returns
- /// true; otherwise, returns nullptr.
- //------------------------------------------------------------------
- static DNBCallbackLog
- GetLogFunction();
-
- static bool
- StartCollectingForProcess(nub_process_t pid, const JSONObject &config);
-
- static bool
- CancelStreamForProcess(nub_process_t pid);
-
- static DarwinLogEventVector
- GetEventsForProcess(nub_process_t pid);
-
- ~DarwinLogCollector();
-
- pid_t
- GetProcessID() const
- {
- return m_pid;
- }
-
- //------------------------------------------------------------------
- // ActivityStore API
- //------------------------------------------------------------------
- const char*
- GetActivityForID(os_activity_id_t activity_id) const override;
+ std::string
+ GetActivityChainForID(os_activity_id_t activity_id) const override;
- std::string
- GetActivityChainForID(os_activity_id_t activity_id) const override;
+private:
+ DarwinLogCollector() = delete;
+ DarwinLogCollector(const DarwinLogCollector &) = delete;
+ DarwinLogCollector &operator=(const DarwinLogCollector &) = delete;
+ explicit DarwinLogCollector(nub_process_t pid,
+ const LogFilterChainSP &filter_chain_sp);
-private:
+ void SignalDataAvailable();
+
+ void SetActivityStream(os_activity_stream_t activity_stream);
+
+ bool HandleStreamEntry(os_activity_stream_entry_t entry, int error);
+
+ DarwinLogEventVector RemoveEvents();
+
+ void CancelActivityStream();
+
+ void GetActivityChainForID_internal(os_activity_id_t activity_id,
+ std::string &result, size_t depth) const;
+
+ struct ActivityInfo {
+ ActivityInfo(const char *name, os_activity_id_t activity_id,
+ os_activity_id_t parent_activity_id)
+ : m_name(name), m_id(activity_id), m_parent_id(parent_activity_id) {}
+
+ const std::string m_name;
+ const os_activity_id_t m_id;
+ const os_activity_id_t m_parent_id;
+ };
+
+ using ActivityMap = std::unordered_map<os_activity_id_t, ActivityInfo>;
+
+ const nub_process_t m_pid;
+ os_activity_stream_t m_activity_stream;
+ DarwinLogEventVector m_events;
+ std::mutex m_events_mutex;
+ LogFilterChainSP m_filter_chain_sp;
- DarwinLogCollector() = delete;
- DarwinLogCollector(const DarwinLogCollector&) = delete;
- DarwinLogCollector &operator=(const DarwinLogCollector&) = delete;
-
- explicit
- DarwinLogCollector(nub_process_t pid,
- const LogFilterChainSP &filter_chain_sp);
-
- void
- SignalDataAvailable();
-
- void
- SetActivityStream(os_activity_stream_t activity_stream);
-
- bool
- HandleStreamEntry(os_activity_stream_entry_t entry, int error);
-
- DarwinLogEventVector
- RemoveEvents();
-
- void
- CancelActivityStream();
-
- void
- GetActivityChainForID_internal(os_activity_id_t activity_id,
- std::string &result, size_t depth) const;
-
- struct ActivityInfo
- {
- ActivityInfo(const char *name, os_activity_id_t activity_id,
- os_activity_id_t parent_activity_id) :
- m_name(name),
- m_id(activity_id),
- m_parent_id(parent_activity_id)
- {
- }
-
- const std::string m_name;
- const os_activity_id_t m_id;
- const os_activity_id_t m_parent_id;
- };
-
- using ActivityMap = std::unordered_map<os_activity_id_t, ActivityInfo>;
-
- const nub_process_t m_pid;
- os_activity_stream_t m_activity_stream;
- DarwinLogEventVector m_events;
- std::mutex m_events_mutex;
- LogFilterChainSP m_filter_chain_sp;
-
- /// Mutex to protect activity info (activity name and parent structures)
- mutable std::mutex m_activity_info_mutex;
- /// Map of activity id to ActivityInfo
- ActivityMap m_activity_map;
+ /// Mutex to protect activity info (activity name and parent structures)
+ mutable std::mutex m_activity_info_mutex;
+ /// Map of activity id to ActivityInfo
+ ActivityMap m_activity_map;
};
#endif /* LogStreamCollector_h */
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h Tue Sep 6 15:57:50 2016
@@ -10,14 +10,13 @@
#ifndef DarwinLogTypes_h
#define DarwinLogTypes_h
-enum FilterTarget
-{
- eFilterTargetInvalid,
- eFilterTargetActivity,
- eFilterTargetActivityChain,
- eFilterTargetCategory,
- eFilterTargetMessage,
- eFilterTargetSubsystem
+enum FilterTarget {
+ eFilterTargetInvalid,
+ eFilterTargetActivity,
+ eFilterTargetActivityChain,
+ eFilterTargetCategory,
+ eFilterTargetMessage,
+ eFilterTargetSubsystem
};
#endif /* DarwinLogTypes_h */
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp Tue Sep 6 15:57:50 2016
@@ -9,6 +9,4 @@
#include "LogFilter.h"
-LogFilter::~LogFilter()
-{
-}
+LogFilter::~LogFilter() {}
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h Tue Sep 6 15:57:50 2016
@@ -12,33 +12,19 @@
#include "DarwinLogInterfaces.h"
-class LogFilter
-{
+class LogFilter {
public:
+ virtual ~LogFilter();
- virtual
- ~LogFilter();
+ virtual bool DoesMatch(const LogMessage &message) const = 0;
- virtual bool
- DoesMatch(const LogMessage &message) const = 0;
-
- bool
- MatchesAreAccepted() const
- {
- return m_matches_accept;
- }
+ bool MatchesAreAccepted() const { return m_matches_accept; }
protected:
-
- LogFilter(bool matches_accept) :
- m_matches_accept(matches_accept)
- {
- }
+ LogFilter(bool matches_accept) : m_matches_accept(matches_accept) {}
private:
-
- bool m_matches_accept;
-
+ bool m_matches_accept;
};
#endif /* LogFilter_h */
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp Tue Sep 6 15:57:50 2016
@@ -11,51 +11,32 @@
#include "LogFilter.h"
-LogFilterChain::LogFilterChain(bool default_accept) :
- m_filters(),
- m_default_accept(default_accept)
-{
-}
+LogFilterChain::LogFilterChain(bool default_accept)
+ : m_filters(), m_default_accept(default_accept) {}
-void
-LogFilterChain::AppendFilter(const LogFilterSP &filter_sp)
-{
- if (filter_sp)
- m_filters.push_back(filter_sp);
+void LogFilterChain::AppendFilter(const LogFilterSP &filter_sp) {
+ if (filter_sp)
+ m_filters.push_back(filter_sp);
}
-void
-LogFilterChain::ClearFilterChain()
-{
- m_filters.clear();
-}
+void LogFilterChain::ClearFilterChain() { m_filters.clear(); }
-bool
-LogFilterChain::GetDefaultAccepts() const
-{
- return m_default_accept;
-}
+bool LogFilterChain::GetDefaultAccepts() const { return m_default_accept; }
-void
-LogFilterChain::SetDefaultAccepts(bool default_accept)
-{
- m_default_accept = default_accept;
+void LogFilterChain::SetDefaultAccepts(bool default_accept) {
+ m_default_accept = default_accept;
}
-bool
-LogFilterChain::GetAcceptMessage(const LogMessage &message) const
-{
- for (auto filter_sp : m_filters)
- {
- if (filter_sp->DoesMatch(message))
- {
- // This message matches this filter. If the filter accepts matches,
- // this message matches; otherwise, it rejects matches.
- return filter_sp->MatchesAreAccepted();
- }
+bool LogFilterChain::GetAcceptMessage(const LogMessage &message) const {
+ for (auto filter_sp : m_filters) {
+ if (filter_sp->DoesMatch(message)) {
+ // This message matches this filter. If the filter accepts matches,
+ // this message matches; otherwise, it rejects matches.
+ return filter_sp->MatchesAreAccepted();
}
+ }
- // None of the filters matched. Therefore, we do whatever the
- // default fall-through rule says.
- return m_default_accept;
+ // None of the filters matched. Therefore, we do whatever the
+ // default fall-through rule says.
+ return m_default_accept;
}
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h Tue Sep 6 15:57:50 2016
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef LogFilterChain_h
#define LogFilterChain_h
@@ -15,34 +14,25 @@
#include "DarwinLogInterfaces.h"
-class LogFilterChain
-{
+class LogFilterChain {
public:
+ LogFilterChain(bool default_accept);
- LogFilterChain(bool default_accept);
-
- void
- AppendFilter(const LogFilterSP &filter_sp);
+ void AppendFilter(const LogFilterSP &filter_sp);
- void
- ClearFilterChain();
+ void ClearFilterChain();
- bool
- GetDefaultAccepts() const;
+ bool GetDefaultAccepts() const;
- void
- SetDefaultAccepts(bool default_accepts);
+ void SetDefaultAccepts(bool default_accepts);
- bool
- GetAcceptMessage(const LogMessage &message) const;
+ bool GetAcceptMessage(const LogMessage &message) const;
private:
+ using FilterVector = std::vector<LogFilterSP>;
- using FilterVector = std::vector<LogFilterSP>;
-
- FilterVector m_filters;
- bool m_default_accept;
-
+ FilterVector m_filters;
+ bool m_default_accept;
};
#endif /* LogFilterChain_hpp */
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp Tue Sep 6 15:57:50 2016
@@ -12,46 +12,38 @@
LogFilterExactMatch::LogFilterExactMatch(bool match_accepts,
FilterTarget filter_target,
- const std::string &match_text) :
- LogFilter(match_accepts),
- m_filter_target(filter_target),
- m_match_text(match_text)
-{
-}
+ const std::string &match_text)
+ : LogFilter(match_accepts), m_filter_target(filter_target),
+ m_match_text(match_text) {}
-bool
-LogFilterExactMatch::DoesMatch(const LogMessage &message) const
-{
- switch (m_filter_target)
- {
- case eFilterTargetActivity:
- // Empty fields never match a condition.
- if (!message.HasActivity())
- return false;
- return m_match_text == message.GetActivity();
- case eFilterTargetActivityChain:
- // Empty fields never match a condition.
- if (!message.HasActivity())
- return false;
- return m_match_text == message.GetActivityChain();
- case eFilterTargetCategory:
- // Empty fields never match a condition.
- if (!message.HasCategory())
- return false;
- return m_match_text == message.GetCategory();
- case eFilterTargetMessage:
- {
- const char *message_text = message.GetMessage();
- return (message_text != nullptr) &&
- (m_match_text == message_text);
- }
- case eFilterTargetSubsystem:
- // Empty fields never match a condition.
- if (!message.HasSubsystem())
- return false;
- return m_match_text == message.GetSubsystem();
- default:
- // We don't know this type.
- return false;
- }
+bool LogFilterExactMatch::DoesMatch(const LogMessage &message) const {
+ switch (m_filter_target) {
+ case eFilterTargetActivity:
+ // Empty fields never match a condition.
+ if (!message.HasActivity())
+ return false;
+ return m_match_text == message.GetActivity();
+ case eFilterTargetActivityChain:
+ // Empty fields never match a condition.
+ if (!message.HasActivity())
+ return false;
+ return m_match_text == message.GetActivityChain();
+ case eFilterTargetCategory:
+ // Empty fields never match a condition.
+ if (!message.HasCategory())
+ return false;
+ return m_match_text == message.GetCategory();
+ case eFilterTargetMessage: {
+ const char *message_text = message.GetMessage();
+ return (message_text != nullptr) && (m_match_text == message_text);
+ }
+ case eFilterTargetSubsystem:
+ // Empty fields never match a condition.
+ if (!message.HasSubsystem())
+ return false;
+ return m_match_text == message.GetSubsystem();
+ default:
+ // We don't know this type.
+ return false;
+ }
}
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h Tue Sep 6 15:57:50 2016
@@ -16,21 +16,16 @@
#include "DarwinLogTypes.h"
#include "LogFilter.h"
-class LogFilterExactMatch : public LogFilter
-{
+class LogFilterExactMatch : public LogFilter {
public:
+ LogFilterExactMatch(bool match_accepts, FilterTarget filter_target,
+ const std::string &match_text);
- LogFilterExactMatch(bool match_accepts, FilterTarget filter_target,
- const std::string &match_text);
-
- bool
- DoesMatch(const LogMessage &message) const override;
+ bool DoesMatch(const LogMessage &message) const override;
private:
-
- const FilterTarget m_filter_target;
- const std::string m_match_text;
-
+ const FilterTarget m_filter_target;
+ const std::string m_match_text;
};
#endif
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp Tue Sep 6 15:57:50 2016
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
#include "LogFilterRegex.h"
#include "DNBLog.h"
@@ -19,100 +18,80 @@
// everywhere.
//----------------------------------------------------------------------
#if defined(REG_ENHANCED)
-#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED|REG_EXTENDED)
+#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED | REG_EXTENDED)
#else
#define DEFAULT_COMPILE_FLAGS (REG_EXTENDED)
#endif
-LogFilterRegex::LogFilterRegex(bool match_accepts,
- FilterTarget filter_target,
- const std::string ®ex) :
- LogFilter(match_accepts),
- m_filter_target(filter_target),
- m_regex_text(regex),
- m_regex(),
- m_is_valid(false),
- m_error_text()
-{
- // Clear it.
- memset(&m_regex, 0, sizeof(m_regex));
-
- // Compile it.
- if (!regex.empty())
- {
- auto comp_err = ::regcomp(&m_regex, regex.c_str(),
- DEFAULT_COMPILE_FLAGS);
- m_is_valid = (comp_err == 0);
- if (!m_is_valid)
- {
- char buffer[256];
- buffer[0] = '\0';
- ::regerror(comp_err, &m_regex, buffer, sizeof(buffer));
- m_error_text = buffer;
- }
+LogFilterRegex::LogFilterRegex(bool match_accepts, FilterTarget filter_target,
+ const std::string ®ex)
+ : LogFilter(match_accepts), m_filter_target(filter_target),
+ m_regex_text(regex), m_regex(), m_is_valid(false), m_error_text() {
+ // Clear it.
+ memset(&m_regex, 0, sizeof(m_regex));
+
+ // Compile it.
+ if (!regex.empty()) {
+ auto comp_err = ::regcomp(&m_regex, regex.c_str(), DEFAULT_COMPILE_FLAGS);
+ m_is_valid = (comp_err == 0);
+ if (!m_is_valid) {
+ char buffer[256];
+ buffer[0] = '\0';
+ ::regerror(comp_err, &m_regex, buffer, sizeof(buffer));
+ m_error_text = buffer;
}
+ }
}
-LogFilterRegex::~LogFilterRegex()
-{
- if (m_is_valid)
- {
- // Free the regex internals.
- regfree(&m_regex);
- }
+LogFilterRegex::~LogFilterRegex() {
+ if (m_is_valid) {
+ // Free the regex internals.
+ regfree(&m_regex);
+ }
}
-bool
-LogFilterRegex::DoesMatch(const LogMessage &message) const
-{
- switch (m_filter_target)
- {
- case eFilterTargetActivity:
- // Empty fields never match a condition.
- if (!message.HasActivity())
- return false;
- return ::regexec(&m_regex, message.GetActivity(), 0, nullptr, 0)
- == 0;
- case eFilterTargetActivityChain:
- // Empty fields never match a condition.
- if (!message.HasActivity())
- return false;
- return ::regexec(&m_regex, message.GetActivityChain().c_str(), 0,
- nullptr, 0) == 0;
- case eFilterTargetCategory:
- // Empty fields never match a condition.
- if (!message.HasCategory())
- return false;
- return ::regexec(&m_regex, message.GetCategory(), 0, nullptr,
- 0) == 0;
- case eFilterTargetMessage:
- {
- const char *message_text = message.GetMessage();
- if (!message_text)
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG, "LogFilterRegex: regex "
- "\"%s\" no match due to nullptr message.",
- m_regex_text.c_str());
- return false;
- }
-
- bool match = ::regexec(&m_regex, message_text, 0,
- nullptr, 0) == 0;
- DNBLogThreadedIf(LOG_DARWIN_LOG, "LogFilterRegex: regex "
- "\"%s\" %s message \"%s\".",
- m_regex_text.c_str(),
- match ? "matches" : "does not match",
- message_text);
- return match;
- }
- case eFilterTargetSubsystem:
- // Empty fields never match a condition.
- if (!message.HasSubsystem())
- return false;
- return ::regexec(&m_regex, message.GetSubsystem(), 0, nullptr,
- 0) == 0;
- default:
- // We don't know this type.
- return false;
+bool LogFilterRegex::DoesMatch(const LogMessage &message) const {
+ switch (m_filter_target) {
+ case eFilterTargetActivity:
+ // Empty fields never match a condition.
+ if (!message.HasActivity())
+ return false;
+ return ::regexec(&m_regex, message.GetActivity(), 0, nullptr, 0) == 0;
+ case eFilterTargetActivityChain:
+ // Empty fields never match a condition.
+ if (!message.HasActivity())
+ return false;
+ return ::regexec(&m_regex, message.GetActivityChain().c_str(), 0, nullptr,
+ 0) == 0;
+ case eFilterTargetCategory:
+ // Empty fields never match a condition.
+ if (!message.HasCategory())
+ return false;
+ return ::regexec(&m_regex, message.GetCategory(), 0, nullptr, 0) == 0;
+ case eFilterTargetMessage: {
+ const char *message_text = message.GetMessage();
+ if (!message_text) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG,
+ "LogFilterRegex: regex "
+ "\"%s\" no match due to nullptr message.",
+ m_regex_text.c_str());
+ return false;
}
+
+ bool match = ::regexec(&m_regex, message_text, 0, nullptr, 0) == 0;
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "LogFilterRegex: regex "
+ "\"%s\" %s message \"%s\".",
+ m_regex_text.c_str(), match ? "matches" : "does not match",
+ message_text);
+ return match;
+ }
+ case eFilterTargetSubsystem:
+ // Empty fields never match a condition.
+ if (!message.HasSubsystem())
+ return false;
+ return ::regexec(&m_regex, message.GetSubsystem(), 0, nullptr, 0) == 0;
+ default:
+ // We don't know this type.
+ return false;
+ }
}
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h Tue Sep 6 15:57:50 2016
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef LogFilterRegex_h
#define LogFilterRegex_h
@@ -21,38 +20,25 @@
#include "DarwinLogTypes.h"
#include "LogFilter.h"
-class LogFilterRegex : public LogFilter
-{
+class LogFilterRegex : public LogFilter {
public:
+ LogFilterRegex(bool match_accepts, FilterTarget filter_target,
+ const std::string ®ex);
- LogFilterRegex(bool match_accepts, FilterTarget filter_target,
- const std::string ®ex);
+ virtual ~LogFilterRegex();
- virtual
- ~LogFilterRegex();
+ bool IsValid() const { return m_is_valid; }
- bool
- IsValid() const
- {
- return m_is_valid;
- }
-
- const char*
- GetErrorAsCString() const
- {
- return m_error_text.c_str();
- }
+ const char *GetErrorAsCString() const { return m_error_text.c_str(); }
- bool
- DoesMatch(const LogMessage &message) const override;
+ bool DoesMatch(const LogMessage &message) const override;
private:
-
- const FilterTarget m_filter_target;
- const std::string m_regex_text;
- regex_t m_regex;
- bool m_is_valid;
- std::string m_error_text;
+ const FilterTarget m_filter_target;
+ const std::string m_regex_text;
+ regex_t m_regex;
+ bool m_is_valid;
+ std::string m_error_text;
};
#endif /* LogFilterSubsystemRegex_hpp */
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp Tue Sep 6 15:57:50 2016
@@ -7,13 +7,8 @@
//
//===----------------------------------------------------------------------===//
-
#include "LogMessage.h"
-LogMessage::LogMessage()
-{
-}
+LogMessage::LogMessage() {}
-LogMessage::~LogMessage()
-{
-}
+LogMessage::~LogMessage() {}
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h Tue Sep 6 15:57:50 2016
@@ -12,42 +12,29 @@
#include <string>
-class LogMessage
-{
+class LogMessage {
public:
+ virtual ~LogMessage();
- virtual
- ~LogMessage();
+ virtual bool HasActivity() const = 0;
- virtual bool
- HasActivity() const = 0;
+ virtual const char *GetActivity() const = 0;
- virtual const char*
- GetActivity() const = 0;
+ virtual std::string GetActivityChain() const = 0;
- virtual std::string
- GetActivityChain() const = 0;
+ virtual bool HasCategory() const = 0;
- virtual bool
- HasCategory() const = 0;
+ virtual const char *GetCategory() const = 0;
- virtual const char*
- GetCategory() const = 0;
+ virtual bool HasSubsystem() const = 0;
- virtual bool
- HasSubsystem() const = 0;
+ virtual const char *GetSubsystem() const = 0;
- virtual const char*
- GetSubsystem() const = 0;
-
- // This can be expensive, so once we ask for it, we'll cache the result.
- virtual const char*
- GetMessage() const = 0;
+ // This can be expensive, so once we ask for it, we'll cache the result.
+ virtual const char *GetMessage() const = 0;
protected:
-
- LogMessage();
-
+ LogMessage();
};
#endif /* LogMessage_h */
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp Tue Sep 6 15:57:50 2016
@@ -12,84 +12,57 @@
#include "ActivityStore.h"
#include "ActivityStreamSPI.h"
-namespace
-{
- static os_log_copy_formatted_message_t s_log_copy_formatted_message;
+namespace {
+static os_log_copy_formatted_message_t s_log_copy_formatted_message;
}
-void
-LogMessageOsLog::SetFormatterFunction(os_log_copy_formatted_message_t
- format_func)
-{
- s_log_copy_formatted_message = format_func;
+void LogMessageOsLog::SetFormatterFunction(
+ os_log_copy_formatted_message_t format_func) {
+ s_log_copy_formatted_message = format_func;
}
LogMessageOsLog::LogMessageOsLog(const ActivityStore &activity_store,
- ActivityStreamEntry &entry) :
- LogMessage(),
- m_activity_store(activity_store),
- m_entry(entry),
- m_message()
-{
-}
+ ActivityStreamEntry &entry)
+ : LogMessage(), m_activity_store(activity_store), m_entry(entry),
+ m_message() {}
-bool
-LogMessageOsLog::HasActivity() const
-{
- return m_entry.activity_id != 0;
-}
+bool LogMessageOsLog::HasActivity() const { return m_entry.activity_id != 0; }
-const char*
-LogMessageOsLog::GetActivity() const
-{
- return m_activity_store.GetActivityForID(m_entry.activity_id);
+const char *LogMessageOsLog::GetActivity() const {
+ return m_activity_store.GetActivityForID(m_entry.activity_id);
}
-std::string
-LogMessageOsLog::GetActivityChain() const
-{
- return m_activity_store.GetActivityChainForID(m_entry.activity_id);
+std::string LogMessageOsLog::GetActivityChain() const {
+ return m_activity_store.GetActivityChainForID(m_entry.activity_id);
}
-bool
-LogMessageOsLog::HasCategory() const
-{
- return m_entry.log_message.category &&
- (m_entry.log_message.category[0] != 0);
+bool LogMessageOsLog::HasCategory() const {
+ return m_entry.log_message.category && (m_entry.log_message.category[0] != 0);
}
-const char*
-LogMessageOsLog::GetCategory() const
-{
- return m_entry.log_message.category;
+const char *LogMessageOsLog::GetCategory() const {
+ return m_entry.log_message.category;
}
-bool
-LogMessageOsLog::HasSubsystem() const
-{
- return m_entry.log_message.subsystem &&
- (m_entry.log_message.subsystem[0] != 0);
+bool LogMessageOsLog::HasSubsystem() const {
+ return m_entry.log_message.subsystem &&
+ (m_entry.log_message.subsystem[0] != 0);
}
-const char*
-LogMessageOsLog::GetSubsystem() const
-{
- return m_entry.log_message.subsystem;
+const char *LogMessageOsLog::GetSubsystem() const {
+ return m_entry.log_message.subsystem;
}
-const char*
-LogMessageOsLog::GetMessage() const
-{
- if (m_message.empty())
- {
- std::unique_ptr<char[]> formatted_message(
- s_log_copy_formatted_message(&m_entry.log_message));
- if (formatted_message)
- m_message = formatted_message.get();
- // else
- // TODO log
- }
+const char *LogMessageOsLog::GetMessage() const {
+ if (m_message.empty()) {
+ std::unique_ptr<char[]> formatted_message(
+ s_log_copy_formatted_message(&m_entry.log_message));
+ if (formatted_message)
+ m_message = formatted_message.get();
+ // else
+ // TODO log
+ }
- // This is safe to return as we're not modifying it once we've formatted it.
- return m_message.c_str();
+ // This is safe to return as we're not modifying it once we've formatted it.
+ return m_message.c_str();
}
Modified: lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h Tue Sep 6 15:57:50 2016
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef LogMessageOsLog_h
#define LogMessageOsLog_h
@@ -26,48 +25,35 @@ using ActivityStreamEntry = struct os_ac
/// outlive this LogMessageOsLog entry.
// -----------------------------------------------------------------------------
-class LogMessageOsLog : public LogMessage
-{
+class LogMessageOsLog : public LogMessage {
public:
+ static void SetFormatterFunction(os_log_copy_formatted_message_t format_func);
- static void
- SetFormatterFunction(os_log_copy_formatted_message_t format_func);
-
- LogMessageOsLog(const ActivityStore &activity_store,
- ActivityStreamEntry &entry);
+ LogMessageOsLog(const ActivityStore &activity_store,
+ ActivityStreamEntry &entry);
- // API methods
+ // API methods
- bool
- HasActivity() const override;
+ bool HasActivity() const override;
- const char*
- GetActivity() const override;
+ const char *GetActivity() const override;
- std::string
- GetActivityChain() const override;
+ std::string GetActivityChain() const override;
- bool
- HasCategory() const override;
+ bool HasCategory() const override;
- const char*
- GetCategory() const override;
+ const char *GetCategory() const override;
- bool
- HasSubsystem() const override;
+ bool HasSubsystem() const override;
- const char*
- GetSubsystem() const override;
+ const char *GetSubsystem() const override;
- const char*
- GetMessage() const override;
+ const char *GetMessage() const override;
private:
-
- const ActivityStore &m_activity_store;
- ActivityStreamEntry &m_entry;
- mutable std::string m_message;
-
+ const ActivityStore &m_activity_store;
+ ActivityStreamEntry &m_entry;
+ mutable std::string m_message;
};
#endif /* LogMessageOsLog_h */
Modified: lldb/trunk/tools/debugserver/source/MacOSX/Genealogy.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/Genealogy.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/Genealogy.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/Genealogy.cpp Tue Sep 6 15:57:50 2016
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
#include <Availability.h>
-#include <string>
#include <dlfcn.h>
+#include <string>
#include <uuid/uuid.h>
#include "DNBDefs.h"
@@ -21,280 +21,299 @@
/// Constructor
//---------------------------
-Genealogy::Genealogy () :
- m_os_activity_diagnostic_for_pid (nullptr),
- m_os_activity_iterate_processes (nullptr),
- m_os_activity_iterate_breadcrumbs (nullptr),
- m_os_activity_iterate_messages (nullptr),
- m_os_activity_iterate_activities (nullptr),
- m_os_trace_get_type (nullptr),
- m_os_trace_copy_formatted_message (nullptr),
- m_os_activity_for_thread (nullptr),
- m_os_activity_for_task_thread (nullptr),
- m_thread_activities(),
- m_process_executable_infos(),
- m_diagnosticd_call_timed_out(false)
-{
- m_os_activity_diagnostic_for_pid = (bool (*)(pid_t, os_activity_t, uint32_t, os_diagnostic_block_t))dlsym (RTLD_DEFAULT, "os_activity_diagnostic_for_pid");
- m_os_activity_iterate_processes = (void (*)(os_activity_process_list_t, bool (^)(os_activity_process_t)))dlsym (RTLD_DEFAULT, "os_activity_iterate_processes");
- m_os_activity_iterate_breadcrumbs = (void (*)(os_activity_process_t, bool (^)(os_activity_breadcrumb_t))) dlsym (RTLD_DEFAULT, "os_activity_iterate_breadcrumbs");
- m_os_activity_iterate_messages = (void (*)(os_trace_message_list_t, os_activity_process_t, bool (^)(os_trace_message_t)))dlsym (RTLD_DEFAULT, "os_activity_iterate_messages");
- m_os_activity_iterate_activities = (void (*)(os_activity_list_t, os_activity_process_t, bool (^)(os_activity_entry_t)))dlsym (RTLD_DEFAULT, "os_activity_iterate_activities");
- m_os_trace_get_type = (uint8_t (*)(os_trace_message_t)) dlsym (RTLD_DEFAULT, "os_trace_get_type");
- m_os_trace_copy_formatted_message = (char *(*)(os_trace_message_t)) dlsym (RTLD_DEFAULT, "os_trace_copy_formatted_message");
- m_os_activity_for_thread = (os_activity_t (*)(os_activity_process_t, uint64_t)) dlsym (RTLD_DEFAULT, "os_activity_for_thread");
- m_os_activity_for_task_thread = (os_activity_t (*)(task_t, uint64_t)) dlsym (RTLD_DEFAULT, "os_activity_for_task_thread");
- m_os_activity_messages_for_thread = (os_trace_message_list_t (*) (os_activity_process_t process, os_activity_t activity, uint64_t thread_id)) dlsym (RTLD_DEFAULT, "os_activity_messages_for_thread");
+Genealogy::Genealogy()
+ : m_os_activity_diagnostic_for_pid(nullptr),
+ m_os_activity_iterate_processes(nullptr),
+ m_os_activity_iterate_breadcrumbs(nullptr),
+ m_os_activity_iterate_messages(nullptr),
+ m_os_activity_iterate_activities(nullptr), m_os_trace_get_type(nullptr),
+ m_os_trace_copy_formatted_message(nullptr),
+ m_os_activity_for_thread(nullptr), m_os_activity_for_task_thread(nullptr),
+ m_thread_activities(), m_process_executable_infos(),
+ m_diagnosticd_call_timed_out(false) {
+ m_os_activity_diagnostic_for_pid =
+ (bool (*)(pid_t, os_activity_t, uint32_t, os_diagnostic_block_t))dlsym(
+ RTLD_DEFAULT, "os_activity_diagnostic_for_pid");
+ m_os_activity_iterate_processes =
+ (void (*)(os_activity_process_list_t, bool (^)(os_activity_process_t)))
+ dlsym(RTLD_DEFAULT, "os_activity_iterate_processes");
+ m_os_activity_iterate_breadcrumbs =
+ (void (*)(os_activity_process_t, bool (^)(os_activity_breadcrumb_t)))
+ dlsym(RTLD_DEFAULT, "os_activity_iterate_breadcrumbs");
+ m_os_activity_iterate_messages = (void (*)(
+ os_trace_message_list_t, os_activity_process_t,
+ bool (^)(os_trace_message_t)))dlsym(RTLD_DEFAULT,
+ "os_activity_iterate_messages");
+ m_os_activity_iterate_activities = (void (*)(
+ os_activity_list_t, os_activity_process_t,
+ bool (^)(os_activity_entry_t)))dlsym(RTLD_DEFAULT,
+ "os_activity_iterate_activities");
+ m_os_trace_get_type =
+ (uint8_t(*)(os_trace_message_t))dlsym(RTLD_DEFAULT, "os_trace_get_type");
+ m_os_trace_copy_formatted_message = (char *(*)(os_trace_message_t))dlsym(
+ RTLD_DEFAULT, "os_trace_copy_formatted_message");
+ m_os_activity_for_thread =
+ (os_activity_t(*)(os_activity_process_t, uint64_t))dlsym(
+ RTLD_DEFAULT, "os_activity_for_thread");
+ m_os_activity_for_task_thread = (os_activity_t(*)(task_t, uint64_t))dlsym(
+ RTLD_DEFAULT, "os_activity_for_task_thread");
+ m_os_activity_messages_for_thread = (os_trace_message_list_t(*)(
+ os_activity_process_t process, os_activity_t activity,
+ uint64_t thread_id))dlsym(RTLD_DEFAULT,
+ "os_activity_messages_for_thread");
}
Genealogy::ThreadActivitySP
-Genealogy::GetGenealogyInfoForThread (pid_t pid, nub_thread_t tid, const MachThreadList &thread_list, task_t task, bool &timed_out)
-{
- ThreadActivitySP activity;
- //
- // if we've timed out trying to get the activities, don't try again at this process stop.
- // (else we'll need to hit the timeout for every thread we're asked about.)
- // We'll try again at the next public stop.
-
- if (m_thread_activities.size() == 0 && m_diagnosticd_call_timed_out == false)
- {
- GetActivities(pid, thread_list, task);
- }
- std::map<nub_thread_t, ThreadActivitySP>::const_iterator search;
- search = m_thread_activities.find(tid);
- if (search != m_thread_activities.end())
- {
- activity = search->second;
- }
- timed_out = m_diagnosticd_call_timed_out;
- return activity;
+Genealogy::GetGenealogyInfoForThread(pid_t pid, nub_thread_t tid,
+ const MachThreadList &thread_list,
+ task_t task, bool &timed_out) {
+ ThreadActivitySP activity;
+ //
+ // if we've timed out trying to get the activities, don't try again at this
+ // process stop.
+ // (else we'll need to hit the timeout for every thread we're asked about.)
+ // We'll try again at the next public stop.
+
+ if (m_thread_activities.size() == 0 &&
+ m_diagnosticd_call_timed_out == false) {
+ GetActivities(pid, thread_list, task);
+ }
+ std::map<nub_thread_t, ThreadActivitySP>::const_iterator search;
+ search = m_thread_activities.find(tid);
+ if (search != m_thread_activities.end()) {
+ activity = search->second;
+ }
+ timed_out = m_diagnosticd_call_timed_out;
+ return activity;
}
-void
-Genealogy::Clear()
-{
- m_thread_activities.clear();
- m_diagnosticd_call_timed_out = false;
+void Genealogy::Clear() {
+ m_thread_activities.clear();
+ m_diagnosticd_call_timed_out = false;
}
-void
-Genealogy::GetActivities(pid_t pid, const MachThreadList &thread_list, task_t task)
-{
- if (m_os_activity_diagnostic_for_pid != nullptr
- && m_os_activity_iterate_processes != nullptr
- && m_os_activity_iterate_breadcrumbs != nullptr
- && m_os_activity_iterate_messages != nullptr
- && m_os_activity_iterate_activities != nullptr
- && m_os_trace_get_type != nullptr
- && m_os_trace_copy_formatted_message != nullptr
- && (m_os_activity_for_thread != nullptr || m_os_activity_for_task_thread != nullptr)
- )
- {
- __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- __block BreadcrumbList breadcrumbs;
- __block ActivityList activities;
- __block MessageList messages;
- __block std::map<nub_thread_t, uint64_t> thread_activity_mapping;
-
- os_activity_diagnostic_flag_t flags = OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES | OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY;
- if (m_os_activity_diagnostic_for_pid (pid, 0, flags, ^(os_activity_process_list_t processes, int error)
- {
- if (error == 0)
- {
- m_os_activity_iterate_processes (processes, ^bool(os_activity_process_t process_info)
- {
- if (pid == process_info->pid)
- {
- // Collect all the Breadcrumbs
- m_os_activity_iterate_breadcrumbs (process_info, ^bool(os_activity_breadcrumb_t breadcrumb)
- {
- Breadcrumb bc;
- bc.breadcrumb_id = breadcrumb->breadcrumb_id;
- bc.activity_id = breadcrumb->activity_id;
- bc.timestamp = breadcrumb->timestamp;
- if (breadcrumb->name)
- bc.name = breadcrumb->name;
- breadcrumbs.push_back (bc);
- return true;
+void Genealogy::GetActivities(pid_t pid, const MachThreadList &thread_list,
+ task_t task) {
+ if (m_os_activity_diagnostic_for_pid != nullptr &&
+ m_os_activity_iterate_processes != nullptr &&
+ m_os_activity_iterate_breadcrumbs != nullptr &&
+ m_os_activity_iterate_messages != nullptr &&
+ m_os_activity_iterate_activities != nullptr &&
+ m_os_trace_get_type != nullptr &&
+ m_os_trace_copy_formatted_message != nullptr &&
+ (m_os_activity_for_thread != nullptr ||
+ m_os_activity_for_task_thread != nullptr)) {
+ __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
+ __block BreadcrumbList breadcrumbs;
+ __block ActivityList activities;
+ __block MessageList messages;
+ __block std::map<nub_thread_t, uint64_t> thread_activity_mapping;
+
+ os_activity_diagnostic_flag_t flags =
+ OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES |
+ OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY;
+ if (m_os_activity_diagnostic_for_pid(
+ pid, 0, flags, ^(os_activity_process_list_t processes, int error) {
+ if (error == 0) {
+ m_os_activity_iterate_processes(processes, ^bool(
+ os_activity_process_t
+ process_info) {
+ if (pid == process_info->pid) {
+ // Collect all the Breadcrumbs
+ m_os_activity_iterate_breadcrumbs(
+ process_info,
+ ^bool(os_activity_breadcrumb_t breadcrumb) {
+ Breadcrumb bc;
+ bc.breadcrumb_id = breadcrumb->breadcrumb_id;
+ bc.activity_id = breadcrumb->activity_id;
+ bc.timestamp = breadcrumb->timestamp;
+ if (breadcrumb->name)
+ bc.name = breadcrumb->name;
+ breadcrumbs.push_back(bc);
+ return true;
});
- // Collect all the Activites
- m_os_activity_iterate_activities (process_info->activities, process_info, ^bool(os_activity_entry_t activity)
- {
- Activity ac;
- ac.activity_start = activity->activity_start;
- ac.activity_id = activity->activity_id;
- ac.parent_id = activity->parent_id;
- if (activity->activity_name)
- ac.activity_name = activity->activity_name;
- if (activity->reason)
- ac.reason = activity->reason;
- activities.push_back (ac);
- return true;
+ // Collect all the Activites
+ m_os_activity_iterate_activities(
+ process_info->activities, process_info,
+ ^bool(os_activity_entry_t activity) {
+ Activity ac;
+ ac.activity_start = activity->activity_start;
+ ac.activity_id = activity->activity_id;
+ ac.parent_id = activity->parent_id;
+ if (activity->activity_name)
+ ac.activity_name = activity->activity_name;
+ if (activity->reason)
+ ac.reason = activity->reason;
+ activities.push_back(ac);
+ return true;
});
-
- // Collect all the Messages -- messages not associated with any thread
- m_os_activity_iterate_messages (process_info->messages, process_info, ^bool(os_trace_message_t trace_msg)
- {
- Message msg;
- msg.timestamp = trace_msg->timestamp;
- msg.trace_id = trace_msg->trace_id;
- msg.thread = trace_msg->thread;
- msg.type = m_os_trace_get_type (trace_msg);
- msg.activity_id = 0;
- if (trace_msg->image_uuid && trace_msg->image_path)
- {
- ProcessExecutableInfoSP process_info_sp (new ProcessExecutableInfo());
- uuid_copy (process_info_sp->image_uuid, trace_msg->image_uuid);
- process_info_sp->image_path = trace_msg->image_path;
- msg.process_info_index = AddProcessExecutableInfo (process_info_sp);
- }
- const char *message_text = m_os_trace_copy_formatted_message (trace_msg);
- if (message_text)
- msg.message = message_text;
- messages.push_back (msg);
- return true;
+ // Collect all the Messages -- messages not associated with
+ // any thread
+ m_os_activity_iterate_messages(
+ process_info->messages, process_info,
+ ^bool(os_trace_message_t trace_msg) {
+ Message msg;
+ msg.timestamp = trace_msg->timestamp;
+ msg.trace_id = trace_msg->trace_id;
+ msg.thread = trace_msg->thread;
+ msg.type = m_os_trace_get_type(trace_msg);
+ msg.activity_id = 0;
+ if (trace_msg->image_uuid && trace_msg->image_path) {
+ ProcessExecutableInfoSP process_info_sp(
+ new ProcessExecutableInfo());
+ uuid_copy(process_info_sp->image_uuid,
+ trace_msg->image_uuid);
+ process_info_sp->image_path = trace_msg->image_path;
+ msg.process_info_index =
+ AddProcessExecutableInfo(process_info_sp);
+ }
+ const char *message_text =
+ m_os_trace_copy_formatted_message(trace_msg);
+ if (message_text)
+ msg.message = message_text;
+ messages.push_back(msg);
+ return true;
});
- // Discover which activities are said to be running on threads currently
- const nub_size_t num_threads = thread_list.NumThreads();
- for (nub_size_t i = 0; i < num_threads; ++i)
- {
- nub_thread_t thread_id = thread_list.ThreadIDAtIndex(i);
- os_activity_t act = 0;
- if (m_os_activity_for_task_thread != nullptr)
- {
- act = m_os_activity_for_task_thread (task, thread_id);
- }
- else if (m_os_activity_for_thread != nullptr)
- {
- act = m_os_activity_for_thread (process_info, thread_id);
- }
- if (act != 0)
- thread_activity_mapping[thread_id] = act;
- }
-
- // Collect all Messages -- messages associated with a thread
-
- // When there's no genealogy information, an early version of os_activity_messages_for_thread
- // can crash in rare circumstances. Check to see if this process has any activities before
- // making the call to get messages.
- if (process_info->activities != nullptr && thread_activity_mapping.size() > 0)
- {
- std::map<nub_thread_t, uint64_t>::const_iterator iter;
- for (iter = thread_activity_mapping.begin(); iter != thread_activity_mapping.end(); ++iter)
- {
- nub_thread_t thread_id = iter->first;
- os_activity_t act = iter->second;
- os_trace_message_list_t this_thread_messages = m_os_activity_messages_for_thread (process_info, act, thread_id);
- m_os_activity_iterate_messages (this_thread_messages, process_info, ^bool(os_trace_message_t trace_msg)
- {
- Message msg;
- msg.timestamp = trace_msg->timestamp;
- msg.trace_id = trace_msg->trace_id;
- msg.thread = trace_msg->thread;
- msg.type = m_os_trace_get_type (trace_msg);
- msg.activity_id = act;
- if (trace_msg->image_uuid && trace_msg->image_path)
- {
- ProcessExecutableInfoSP process_info_sp (new ProcessExecutableInfo());
- uuid_copy (process_info_sp->image_uuid, trace_msg->image_uuid);
- process_info_sp->image_path = trace_msg->image_path;
- msg.process_info_index = AddProcessExecutableInfo (process_info_sp);
- }
- const char *message_text = m_os_trace_copy_formatted_message (trace_msg);
- if (message_text)
- msg.message = message_text;
- messages.push_back (msg);
- return true;
- });
- }
- }
+ // Discover which activities are said to be running on
+ // threads currently
+ const nub_size_t num_threads = thread_list.NumThreads();
+ for (nub_size_t i = 0; i < num_threads; ++i) {
+ nub_thread_t thread_id = thread_list.ThreadIDAtIndex(i);
+ os_activity_t act = 0;
+ if (m_os_activity_for_task_thread != nullptr) {
+ act = m_os_activity_for_task_thread(task, thread_id);
+ } else if (m_os_activity_for_thread != nullptr) {
+ act = m_os_activity_for_thread(process_info, thread_id);
+ }
+ if (act != 0)
+ thread_activity_mapping[thread_id] = act;
}
- return true;
- });
- }
- dispatch_semaphore_signal(semaphore);
- }) == true)
- {
- // Wait for the diagnosticd xpc calls to all finish up -- or half a second to elapse.
- dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 2);
- bool success = dispatch_semaphore_wait(semaphore, timeout) == 0;
- if (!success)
- {
- m_diagnosticd_call_timed_out = true;
- return;
- }
- }
- // breadcrumbs, activities, and messages have all now been filled in.
+ // Collect all Messages -- messages associated with a thread
- std::map<nub_thread_t, uint64_t>::const_iterator iter;
- for (iter = thread_activity_mapping.begin(); iter != thread_activity_mapping.end(); ++iter)
- {
- nub_thread_t thread_id = iter->first;
- uint64_t activity_id = iter->second;
- ActivityList::const_iterator activity_search;
- for (activity_search = activities.begin(); activity_search != activities.end(); ++activity_search)
- {
- if (activity_search->activity_id == activity_id)
- {
- ThreadActivitySP thread_activity_sp (new ThreadActivity());
- thread_activity_sp->current_activity = *activity_search;
-
- BreadcrumbList::const_iterator breadcrumb_search;
- for (breadcrumb_search = breadcrumbs.begin(); breadcrumb_search != breadcrumbs.end(); ++breadcrumb_search)
- {
- if (breadcrumb_search->activity_id == activity_id)
- {
- thread_activity_sp->breadcrumbs.push_back (*breadcrumb_search);
- }
- }
- MessageList::const_iterator message_search;
- for (message_search = messages.begin(); message_search != messages.end(); ++message_search)
- {
- if (message_search->thread == thread_id)
- {
- thread_activity_sp->messages.push_back (*message_search);
- }
+ // When there's no genealogy information, an early version
+ // of os_activity_messages_for_thread
+ // can crash in rare circumstances. Check to see if this
+ // process has any activities before
+ // making the call to get messages.
+ if (process_info->activities != nullptr &&
+ thread_activity_mapping.size() > 0) {
+ std::map<nub_thread_t, uint64_t>::const_iterator iter;
+ for (iter = thread_activity_mapping.begin();
+ iter != thread_activity_mapping.end(); ++iter) {
+ nub_thread_t thread_id = iter->first;
+ os_activity_t act = iter->second;
+ os_trace_message_list_t this_thread_messages =
+ m_os_activity_messages_for_thread(process_info, act,
+ thread_id);
+ m_os_activity_iterate_messages(
+ this_thread_messages, process_info,
+ ^bool(os_trace_message_t trace_msg) {
+ Message msg;
+ msg.timestamp = trace_msg->timestamp;
+ msg.trace_id = trace_msg->trace_id;
+ msg.thread = trace_msg->thread;
+ msg.type = m_os_trace_get_type(trace_msg);
+ msg.activity_id = act;
+ if (trace_msg->image_uuid &&
+ trace_msg->image_path) {
+ ProcessExecutableInfoSP process_info_sp(
+ new ProcessExecutableInfo());
+ uuid_copy(process_info_sp->image_uuid,
+ trace_msg->image_uuid);
+ process_info_sp->image_path =
+ trace_msg->image_path;
+ msg.process_info_index =
+ AddProcessExecutableInfo(process_info_sp);
+ }
+ const char *message_text =
+ m_os_trace_copy_formatted_message(trace_msg);
+ if (message_text)
+ msg.message = message_text;
+ messages.push_back(msg);
+ return true;
+ });
+ }
}
-
- m_thread_activities[thread_id] = thread_activity_sp;
- break;
- }
+ }
+ return true;
+ });
+ }
+ dispatch_semaphore_signal(semaphore);
+ }) == true) {
+ // Wait for the diagnosticd xpc calls to all finish up -- or half a second
+ // to elapse.
+ dispatch_time_t timeout =
+ dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 2);
+ bool success = dispatch_semaphore_wait(semaphore, timeout) == 0;
+ if (!success) {
+ m_diagnosticd_call_timed_out = true;
+ return;
+ }
+ }
+
+ // breadcrumbs, activities, and messages have all now been filled in.
+
+ std::map<nub_thread_t, uint64_t>::const_iterator iter;
+ for (iter = thread_activity_mapping.begin();
+ iter != thread_activity_mapping.end(); ++iter) {
+ nub_thread_t thread_id = iter->first;
+ uint64_t activity_id = iter->second;
+ ActivityList::const_iterator activity_search;
+ for (activity_search = activities.begin();
+ activity_search != activities.end(); ++activity_search) {
+ if (activity_search->activity_id == activity_id) {
+ ThreadActivitySP thread_activity_sp(new ThreadActivity());
+ thread_activity_sp->current_activity = *activity_search;
+
+ BreadcrumbList::const_iterator breadcrumb_search;
+ for (breadcrumb_search = breadcrumbs.begin();
+ breadcrumb_search != breadcrumbs.end(); ++breadcrumb_search) {
+ if (breadcrumb_search->activity_id == activity_id) {
+ thread_activity_sp->breadcrumbs.push_back(*breadcrumb_search);
}
+ }
+ MessageList::const_iterator message_search;
+ for (message_search = messages.begin();
+ message_search != messages.end(); ++message_search) {
+ if (message_search->thread == thread_id) {
+ thread_activity_sp->messages.push_back(*message_search);
+ }
+ }
+
+ m_thread_activities[thread_id] = thread_activity_sp;
+ break;
}
+ }
}
+ }
}
uint32_t
-Genealogy::AddProcessExecutableInfo (ProcessExecutableInfoSP process_exe_info)
-{
- const uint32_t info_size = static_cast<uint32_t>(m_process_executable_infos.size());
- for (uint32_t idx = 0; idx < info_size; ++idx)
- {
- if (uuid_compare (m_process_executable_infos[idx]->image_uuid, process_exe_info->image_uuid) == 0)
- {
- return idx + 1;
- }
+Genealogy::AddProcessExecutableInfo(ProcessExecutableInfoSP process_exe_info) {
+ const uint32_t info_size =
+ static_cast<uint32_t>(m_process_executable_infos.size());
+ for (uint32_t idx = 0; idx < info_size; ++idx) {
+ if (uuid_compare(m_process_executable_infos[idx]->image_uuid,
+ process_exe_info->image_uuid) == 0) {
+ return idx + 1;
}
- m_process_executable_infos.push_back (process_exe_info);
- return info_size + 1;
+ }
+ m_process_executable_infos.push_back(process_exe_info);
+ return info_size + 1;
}
Genealogy::ProcessExecutableInfoSP
-Genealogy::GetProcessExecutableInfosAtIndex(size_t idx)
-{
- ProcessExecutableInfoSP info_sp;
- if (idx > 0)
- {
- idx--;
- if (idx <= m_process_executable_infos.size())
- {
- info_sp = m_process_executable_infos[idx];
- }
+Genealogy::GetProcessExecutableInfosAtIndex(size_t idx) {
+ ProcessExecutableInfoSP info_sp;
+ if (idx > 0) {
+ idx--;
+ if (idx <= m_process_executable_infos.size()) {
+ info_sp = m_process_executable_infos[idx];
}
- return info_sp;
+ }
+ return info_sp;
}
-
Modified: lldb/trunk/tools/debugserver/source/MacOSX/Genealogy.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/Genealogy.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/Genealogy.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/Genealogy.h Tue Sep 6 15:57:50 2016
@@ -1,4 +1,5 @@
-//===-- Activity.h -----------------------------------------------*- C++ -*-===//
+//===-- Activity.h -----------------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,107 +11,110 @@
#ifndef __Genealogy_h__
#define __Genealogy_h__
-#include <string>
-#include <vector>
+#include <mach/task.h>
#include <map>
#include <pthread.h>
-#include <mach/task.h>
+#include <string>
+#include <vector>
#include "GenealogySPI.h"
#include "MachThreadList.h"
-class Genealogy
-{
+class Genealogy {
public:
+ Genealogy();
- Genealogy ();
+ ~Genealogy() {}
- ~Genealogy ()
- {
- }
-
- void
- Clear();
-
- struct Breadcrumb
- {
- uint32_t breadcrumb_id;
- uint64_t activity_id;
- uint64_t timestamp;
- std::string name;
- };
-
- struct Activity
- {
- uint64_t activity_start;
- uint64_t activity_id;
- uint64_t parent_id;
- std::string activity_name;
- std::string reason;
- };
-
- struct Message
- {
- uint64_t timestamp;
- uint64_t activity_id;
- uint64_t trace_id;
- uint64_t thread;
- uint8_t type; // OS_TRACE_TYPE_RELEASE, OS_TRACE_TYPE_DEBUG, OS_TRACE_TYPE_ERROR, OS_TRACE_TYPE_FAULT
- uint32_t process_info_index; // index # of the image uuid/file path, 0 means unknown
- std::string message;
- };
-
- typedef std::vector<Message> MessageList;
- typedef std::vector<Breadcrumb> BreadcrumbList;
- typedef std::vector<Activity> ActivityList;
-
- struct ThreadActivity
- {
- Activity current_activity;
- MessageList messages;
- BreadcrumbList breadcrumbs; // should be 0 or 1 breadcrumbs; no more than 1 BC for any given activity
- };
-
- typedef std::shared_ptr<ThreadActivity> ThreadActivitySP;
-
- ThreadActivitySP
- GetGenealogyInfoForThread (pid_t pid, nub_thread_t tid, const MachThreadList &thread_list, task_t task, bool &timed_out);
-
- struct ProcessExecutableInfo
- {
- std::string image_path;
- uuid_t image_uuid;
- };
+ void Clear();
- typedef std::shared_ptr<ProcessExecutableInfo> ProcessExecutableInfoSP;
+ struct Breadcrumb {
+ uint32_t breadcrumb_id;
+ uint64_t activity_id;
+ uint64_t timestamp;
+ std::string name;
+ };
+
+ struct Activity {
+ uint64_t activity_start;
+ uint64_t activity_id;
+ uint64_t parent_id;
+ std::string activity_name;
+ std::string reason;
+ };
+
+ struct Message {
+ uint64_t timestamp;
+ uint64_t activity_id;
+ uint64_t trace_id;
+ uint64_t thread;
+ uint8_t type; // OS_TRACE_TYPE_RELEASE, OS_TRACE_TYPE_DEBUG,
+ // OS_TRACE_TYPE_ERROR, OS_TRACE_TYPE_FAULT
+ uint32_t process_info_index; // index # of the image uuid/file path, 0 means
+ // unknown
+ std::string message;
+ };
+
+ typedef std::vector<Message> MessageList;
+ typedef std::vector<Breadcrumb> BreadcrumbList;
+ typedef std::vector<Activity> ActivityList;
+
+ struct ThreadActivity {
+ Activity current_activity;
+ MessageList messages;
+ BreadcrumbList breadcrumbs; // should be 0 or 1 breadcrumbs; no more than 1
+ // BC for any given activity
+ };
+
+ typedef std::shared_ptr<ThreadActivity> ThreadActivitySP;
+
+ ThreadActivitySP GetGenealogyInfoForThread(pid_t pid, nub_thread_t tid,
+ const MachThreadList &thread_list,
+ task_t task, bool &timed_out);
+
+ struct ProcessExecutableInfo {
+ std::string image_path;
+ uuid_t image_uuid;
+ };
- ProcessExecutableInfoSP
- GetProcessExecutableInfosAtIndex(size_t idx);
+ typedef std::shared_ptr<ProcessExecutableInfo> ProcessExecutableInfoSP;
- uint32_t
- AddProcessExecutableInfo(ProcessExecutableInfoSP process_exe_info);
+ ProcessExecutableInfoSP GetProcessExecutableInfosAtIndex(size_t idx);
-private:
+ uint32_t AddProcessExecutableInfo(ProcessExecutableInfoSP process_exe_info);
- void
- GetActivities(pid_t pid, const MachThreadList &thread_list, task_t task);
+private:
+ void GetActivities(pid_t pid, const MachThreadList &thread_list, task_t task);
- // the spi we need to call into libtrace - look them up via dlsym at runtime
- bool (*m_os_activity_diagnostic_for_pid) (pid_t pid, os_activity_t activity, uint32_t flags, os_diagnostic_block_t block);
- void (*m_os_activity_iterate_processes) (os_activity_process_list_t processes, bool (^iterator)(os_activity_process_t process_info));
- void (*m_os_activity_iterate_breadcrumbs) (os_activity_process_t process_info, bool (^iterator)(os_activity_breadcrumb_t breadcrumb));
- void (*m_os_activity_iterate_messages) (os_trace_message_list_t messages, os_activity_process_t process_info, bool (^iterator)(os_trace_message_t tracemsg));
- void (*m_os_activity_iterate_activities) (os_activity_list_t activities, os_activity_process_t process_info, bool (^iterator)(os_activity_entry_t activity));
- uint8_t (*m_os_trace_get_type) (os_trace_message_t trace_msg);
- char * (*m_os_trace_copy_formatted_message) (os_trace_message_t trace_msg);
- os_activity_t (*m_os_activity_for_thread) (os_activity_process_t process, uint64_t thread_id);
- os_activity_t (*m_os_activity_for_task_thread) (task_t target, uint64_t thread_id);
- os_trace_message_list_t (*m_os_activity_messages_for_thread) (os_activity_process_t process, os_activity_t activity, uint64_t thread_id);
-
-
- std::map<nub_thread_t, ThreadActivitySP> m_thread_activities;
- std::vector<ProcessExecutableInfoSP> m_process_executable_infos;
- bool m_diagnosticd_call_timed_out;
+ // the spi we need to call into libtrace - look them up via dlsym at runtime
+ bool (*m_os_activity_diagnostic_for_pid)(pid_t pid, os_activity_t activity,
+ uint32_t flags,
+ os_diagnostic_block_t block);
+ void (*m_os_activity_iterate_processes)(
+ os_activity_process_list_t processes,
+ bool (^iterator)(os_activity_process_t process_info));
+ void (*m_os_activity_iterate_breadcrumbs)(
+ os_activity_process_t process_info,
+ bool (^iterator)(os_activity_breadcrumb_t breadcrumb));
+ void (*m_os_activity_iterate_messages)(
+ os_trace_message_list_t messages, os_activity_process_t process_info,
+ bool (^iterator)(os_trace_message_t tracemsg));
+ void (*m_os_activity_iterate_activities)(
+ os_activity_list_t activities, os_activity_process_t process_info,
+ bool (^iterator)(os_activity_entry_t activity));
+ uint8_t (*m_os_trace_get_type)(os_trace_message_t trace_msg);
+ char *(*m_os_trace_copy_formatted_message)(os_trace_message_t trace_msg);
+ os_activity_t (*m_os_activity_for_thread)(os_activity_process_t process,
+ uint64_t thread_id);
+ os_activity_t (*m_os_activity_for_task_thread)(task_t target,
+ uint64_t thread_id);
+ os_trace_message_list_t (*m_os_activity_messages_for_thread)(
+ os_activity_process_t process, os_activity_t activity,
+ uint64_t thread_id);
+
+ std::map<nub_thread_t, ThreadActivitySP> m_thread_activities;
+ std::vector<ProcessExecutableInfoSP> m_process_executable_infos;
+ bool m_diagnosticd_call_timed_out;
};
#endif // __Genealogy_h__
Modified: lldb/trunk/tools/debugserver/source/MacOSX/GenealogySPI.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/GenealogySPI.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/GenealogySPI.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/GenealogySPI.h Tue Sep 6 15:57:50 2016
@@ -18,67 +18,65 @@ typedef struct os_activity_watch_s *os_a
typedef uint64_t os_activity_t;
struct os_activity_breadcrumb_s {
- uint32_t breadcrumb_id;
- uint64_t activity_id;
- uint64_t timestamp;
- const char *name;
+ uint32_t breadcrumb_id;
+ uint64_t activity_id;
+ uint64_t timestamp;
+ const char *name;
};
typedef struct os_activity_breadcrumb_s *os_activity_breadcrumb_t;
typedef struct os_trace_message_s {
- uint64_t trace_id;
- uint64_t thread;
- uint64_t timestamp;
- uint32_t offset;
- xpc_object_t __unsafe_unretained payload;
- const uint8_t *image_uuid;
- const char *image_path;
- const char *format;
- const void *buffer;
- size_t bufferLen;
-} *os_trace_message_t;
+ uint64_t trace_id;
+ uint64_t thread;
+ uint64_t timestamp;
+ uint32_t offset;
+ xpc_object_t __unsafe_unretained payload;
+ const uint8_t *image_uuid;
+ const char *image_path;
+ const char *format;
+ const void *buffer;
+ size_t bufferLen;
+} * os_trace_message_t;
typedef struct os_activity_process_s {
- os_activity_process_list_t child_procs;
- os_trace_message_list_t messages;
- os_activity_list_t activities;
- void *breadcrumbs;
- uint64_t proc_id;
- const uint8_t *image_uuid;
- const char *image_path;
- pid_t pid;
-} *os_activity_process_t;
+ os_activity_process_list_t child_procs;
+ os_trace_message_list_t messages;
+ os_activity_list_t activities;
+ void *breadcrumbs;
+ uint64_t proc_id;
+ const uint8_t *image_uuid;
+ const char *image_path;
+ pid_t pid;
+} * os_activity_process_t;
typedef struct os_activity_entry_s {
- uint64_t activity_start;
- os_activity_t activity_id;
- os_activity_t parent_id;
- const char *activity_name;
- const char *reason;
- os_trace_message_list_t messages;
-} *os_activity_entry_t;
-
-enum
-{
- OS_ACTIVITY_DIAGNOSTIC_DEFAULT = 0x00000000,
- OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY = 0x00000001,
- OS_ACTIVITY_DIAGNOSTIC_SKIP_DECODE = 0x00000002,
- OS_ACTIVITY_DIAGNOSTIC_FLATTENED = 0x00000004,
- OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES = 0x00000008,
- OS_ACTIVITY_DIAGNOSTIC_MAX = 0x0000000f
+ uint64_t activity_start;
+ os_activity_t activity_id;
+ os_activity_t parent_id;
+ const char *activity_name;
+ const char *reason;
+ os_trace_message_list_t messages;
+} * os_activity_entry_t;
+
+enum {
+ OS_ACTIVITY_DIAGNOSTIC_DEFAULT = 0x00000000,
+ OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY = 0x00000001,
+ OS_ACTIVITY_DIAGNOSTIC_SKIP_DECODE = 0x00000002,
+ OS_ACTIVITY_DIAGNOSTIC_FLATTENED = 0x00000004,
+ OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES = 0x00000008,
+ OS_ACTIVITY_DIAGNOSTIC_MAX = 0x0000000f
};
typedef uint32_t os_activity_diagnostic_flag_t;
-enum
-{
- OS_ACTIVITY_WATCH_DEFAULT = 0x00000000,
- OS_ACTIVITY_WATCH_PROCESS_ONLY = 0x00000001,
- OS_ACTIVITY_WATCH_SKIP_DECODE = 0x00000002,
- OS_ACTIVITY_WATCH_PAYLOAD = 0x00000004,
- OS_ACTIVITY_WATCH_ERRORS = 0x00000008,
- OS_ACTIVITY_WATCH_FAULTS = 0x00000010,
- OS_ACTIVITY_WATCH_MAX = 0x0000001f
+enum {
+ OS_ACTIVITY_WATCH_DEFAULT = 0x00000000,
+ OS_ACTIVITY_WATCH_PROCESS_ONLY = 0x00000001,
+ OS_ACTIVITY_WATCH_SKIP_DECODE = 0x00000002,
+ OS_ACTIVITY_WATCH_PAYLOAD = 0x00000004,
+ OS_ACTIVITY_WATCH_ERRORS = 0x00000008,
+ OS_ACTIVITY_WATCH_FAULTS = 0x00000010,
+ OS_ACTIVITY_WATCH_MAX = 0x0000001f
};
typedef uint32_t os_activity_watch_flag_t;
@@ -88,9 +86,10 @@ typedef uint32_t os_activity_watch_flag_
#define OS_TRACE_TYPE_ERROR ((1u << 6) | (1u << 0))
#define OS_TRACE_TYPE_FAULT ((1u << 7) | (1u << 6) | (1u << 0))
-
-typedef void (^os_activity_watch_block_t)(os_activity_watch_t watch, os_activity_process_t process_info, bool canceled);
-typedef void (^os_diagnostic_block_t)(os_activity_process_list_t processes, int error);
+typedef void (^os_activity_watch_block_t)(os_activity_watch_t watch,
+ os_activity_process_t process_info,
+ bool canceled);
+typedef void (^os_diagnostic_block_t)(os_activity_process_list_t processes,
+ int error);
#endif
-
Modified: lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.h Tue Sep 6 15:57:50 2016
@@ -10,18 +10,18 @@
#ifndef HasAVX_h
#define HasAVX_h
-#if defined (__i386__) || defined (__x86_64__)
+#if defined(__i386__) || defined(__x86_64__)
#ifdef __cplusplus
extern "C" {
#endif
-int HasAVX ();
+int HasAVX();
#ifdef __cplusplus
}
#endif
#endif
-
+
#endif
Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachException.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachException.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachException.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachException.cpp Tue Sep 6 15:57:50 2016
@@ -12,62 +12,40 @@
//===----------------------------------------------------------------------===//
#include "MachException.h"
-#include "MachProcess.h"
#include "DNB.h"
#include "DNBError.h"
-#include <sys/types.h>
#include "DNBLog.h"
+#include "MachProcess.h"
#include "PThreadMutex.h"
#include "SysSignal.h"
#include <errno.h>
#include <sys/ptrace.h>
+#include <sys/types.h>
// Routine mach_exception_raise
-extern "C"
-kern_return_t catch_mach_exception_raise
-(
- mach_port_t exception_port,
- mach_port_t thread,
- mach_port_t task,
- exception_type_t exception,
- mach_exception_data_t code,
- mach_msg_type_number_t codeCnt
-);
-
-extern "C"
-kern_return_t catch_mach_exception_raise_state
-(
- mach_port_t exception_port,
- exception_type_t exception,
- const mach_exception_data_t code,
- mach_msg_type_number_t codeCnt,
- int *flavor,
- const thread_state_t old_state,
- mach_msg_type_number_t old_stateCnt,
- thread_state_t new_state,
- mach_msg_type_number_t *new_stateCnt
-);
+extern "C" kern_return_t
+catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread,
+ mach_port_t task, exception_type_t exception,
+ mach_exception_data_t code,
+ mach_msg_type_number_t codeCnt);
+
+extern "C" kern_return_t catch_mach_exception_raise_state(
+ mach_port_t exception_port, exception_type_t exception,
+ const mach_exception_data_t code, mach_msg_type_number_t codeCnt,
+ int *flavor, const thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt, thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt);
// Routine mach_exception_raise_state_identity
-extern "C"
-kern_return_t catch_mach_exception_raise_state_identity
-(
- mach_port_t exception_port,
- mach_port_t thread,
- mach_port_t task,
- exception_type_t exception,
- mach_exception_data_t code,
- mach_msg_type_number_t codeCnt,
- int *flavor,
- thread_state_t old_state,
- mach_msg_type_number_t old_stateCnt,
- thread_state_t new_state,
- mach_msg_type_number_t *new_stateCnt
-);
-
-extern "C" boolean_t mach_exc_server(
- mach_msg_header_t *InHeadP,
- mach_msg_header_t *OutHeadP);
+extern "C" kern_return_t catch_mach_exception_raise_state_identity(
+ mach_port_t exception_port, mach_port_t thread, mach_port_t task,
+ exception_type_t exception, mach_exception_data_t code,
+ mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt, thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt);
+
+extern "C" boolean_t mach_exc_server(mach_msg_header_t *InHeadP,
+ mach_msg_header_t *OutHeadP);
// Any access to the g_message variable should be done by locking the
// g_message_mutex first, using the g_message variable, then unlocking
@@ -75,417 +53,339 @@ extern "C" boolean_t mach_exc_server(
// for sample code.
static MachException::Data *g_message = NULL;
-//static pthread_mutex_t g_message_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-
-extern "C"
-kern_return_t
-catch_mach_exception_raise_state
-(
- mach_port_t exc_port,
- exception_type_t exc_type,
- const mach_exception_data_t exc_data,
- mach_msg_type_number_t exc_data_count,
- int * flavor,
- const thread_state_t old_state,
- mach_msg_type_number_t old_stateCnt,
- thread_state_t new_state,
- mach_msg_type_number_t * new_stateCnt
-)
-{
- if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
- {
- DNBLogThreaded ("::%s ( exc_port = 0x%4.4x, exc_type = %d ( %s ), exc_data = 0x%llx, exc_data_count = %d)",
- __FUNCTION__,
- exc_port,
- exc_type, MachException::Name(exc_type),
- (uint64_t)exc_data,
- exc_data_count);
- }
- return KERN_FAILURE;
-}
-
-extern "C"
-kern_return_t
-catch_mach_exception_raise_state_identity
-(
- mach_port_t exc_port,
- mach_port_t thread_port,
- mach_port_t task_port,
- exception_type_t exc_type,
- mach_exception_data_t exc_data,
- mach_msg_type_number_t exc_data_count,
- int * flavor,
- thread_state_t old_state,
- mach_msg_type_number_t old_stateCnt,
- thread_state_t new_state,
- mach_msg_type_number_t *new_stateCnt
-)
-{
- if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
- {
- DNBLogThreaded("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = 0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { 0x%llx, 0x%llx })",
- __FUNCTION__,
- exc_port,
- thread_port,
- task_port,
- exc_type, MachException::Name(exc_type),
- exc_data_count,
- (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD),
- (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD));
- }
- mach_port_deallocate (mach_task_self (), task_port);
- mach_port_deallocate (mach_task_self (), thread_port);
-
- return KERN_FAILURE;
-}
-
-extern "C"
-kern_return_t
-catch_mach_exception_raise
-(
- mach_port_t exc_port,
- mach_port_t thread_port,
- mach_port_t task_port,
- exception_type_t exc_type,
- mach_exception_data_t exc_data,
- mach_msg_type_number_t exc_data_count)
-{
- if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
- {
- DNBLogThreaded ("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = 0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { 0x%llx, 0x%llx })",
- __FUNCTION__,
- exc_port,
- thread_port,
- task_port,
- exc_type, MachException::Name(exc_type),
- exc_data_count,
- (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD),
- (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD));
- }
-
- if (task_port == g_message->task_port)
- {
- g_message->task_port = task_port;
- g_message->thread_port = thread_port;
- g_message->exc_type = exc_type;
- g_message->exc_data.resize(exc_data_count);
- ::memcpy (&g_message->exc_data[0], exc_data, g_message->exc_data.size() * sizeof (mach_exception_data_type_t));
- return KERN_SUCCESS;
- }
- return KERN_FAILURE;
-}
-
+// static pthread_mutex_t g_message_mutex = PTHREAD_MUTEX_INITIALIZER;
-void
-MachException::Message::Dump() const
-{
- DNBLogThreadedIf(LOG_EXCEPTIONS,
- " exc_msg { bits = 0x%8.8x size = 0x%8.8x remote-port = 0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x id = 0x%8.8x } ",
- exc_msg.hdr.msgh_bits,
- exc_msg.hdr.msgh_size,
- exc_msg.hdr.msgh_remote_port,
- exc_msg.hdr.msgh_local_port,
- exc_msg.hdr.msgh_reserved,
- exc_msg.hdr.msgh_id);
-
- DNBLogThreadedIf(LOG_EXCEPTIONS,
- "reply_msg { bits = 0x%8.8x size = 0x%8.8x remote-port = 0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x id = 0x%8.8x }",
- reply_msg.hdr.msgh_bits,
- reply_msg.hdr.msgh_size,
- reply_msg.hdr.msgh_remote_port,
- reply_msg.hdr.msgh_local_port,
- reply_msg.hdr.msgh_reserved,
- reply_msg.hdr.msgh_id);
-
- state.Dump();
-}
-
-bool
-MachException::Data::GetStopInfo(struct DNBThreadStopInfo *stop_info) const
-{
- // Zero out the structure.
- memset(stop_info, 0, sizeof(struct DNBThreadStopInfo));
-
- if (exc_type == 0)
- {
- stop_info->reason = eStopTypeInvalid;
- return true;
- }
-
- // We always stop with a mach exceptions
- stop_info->reason = eStopTypeException;
- // Save the EXC_XXXX exception type
- stop_info->details.exception.type = exc_type;
-
- // Fill in a text description
- const char * exc_name = MachException::Name(exc_type);
- char *desc = stop_info->description;
- const char *end_desc = desc + DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH;
- if (exc_name)
- desc += snprintf(desc, DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH, "%s", exc_name);
- else
- desc += snprintf(desc, DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH, "%i", exc_type);
-
- stop_info->details.exception.data_count = exc_data.size();
-
- int soft_signal = SoftSignal();
- if (soft_signal)
- {
- if (desc < end_desc)
- {
- const char *sig_str = SysSignal::Name(soft_signal);
- snprintf(desc, end_desc - desc, " EXC_SOFT_SIGNAL( %i ( %s ))", soft_signal, sig_str ? sig_str : "unknown signal");
- }
- }
- else
- {
- // No special disassembly for exception data, just
- size_t idx;
- if (desc < end_desc)
- {
- desc += snprintf(desc, end_desc - desc, " data[%llu] = {", (uint64_t)stop_info->details.exception.data_count);
-
- for (idx = 0; desc < end_desc && idx < stop_info->details.exception.data_count; ++idx)
- desc += snprintf(desc, end_desc - desc, "0x%llx%c", (uint64_t)exc_data[idx], ((idx + 1 == stop_info->details.exception.data_count) ? '}' : ','));
- }
- }
-
- // Copy the exception data
- size_t i;
- for (i=0; i<stop_info->details.exception.data_count; i++)
- stop_info->details.exception.data[i] = exc_data[i];
+extern "C" kern_return_t catch_mach_exception_raise_state(
+ mach_port_t exc_port, exception_type_t exc_type,
+ const mach_exception_data_t exc_data, mach_msg_type_number_t exc_data_count,
+ int *flavor, const thread_state_t old_state,
+ mach_msg_type_number_t old_stateCnt, thread_state_t new_state,
+ mach_msg_type_number_t *new_stateCnt) {
+ if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) {
+ DNBLogThreaded("::%s ( exc_port = 0x%4.4x, exc_type = %d ( %s ), exc_data "
+ "= 0x%llx, exc_data_count = %d)",
+ __FUNCTION__, exc_port, exc_type,
+ MachException::Name(exc_type), (uint64_t)exc_data,
+ exc_data_count);
+ }
+ return KERN_FAILURE;
+}
+
+extern "C" kern_return_t catch_mach_exception_raise_state_identity(
+ mach_port_t exc_port, mach_port_t thread_port, mach_port_t task_port,
+ exception_type_t exc_type, mach_exception_data_t exc_data,
+ mach_msg_type_number_t exc_data_count, int *flavor,
+ thread_state_t old_state, mach_msg_type_number_t old_stateCnt,
+ thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) {
+ if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) {
+ DNBLogThreaded("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = "
+ "0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { 0x%llx, "
+ "0x%llx })",
+ __FUNCTION__, exc_port, thread_port, task_port, exc_type,
+ MachException::Name(exc_type), exc_data_count,
+ (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD),
+ (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD));
+ }
+ mach_port_deallocate(mach_task_self(), task_port);
+ mach_port_deallocate(mach_task_self(), thread_port);
+
+ return KERN_FAILURE;
+}
+
+extern "C" kern_return_t
+catch_mach_exception_raise(mach_port_t exc_port, mach_port_t thread_port,
+ mach_port_t task_port, exception_type_t exc_type,
+ mach_exception_data_t exc_data,
+ mach_msg_type_number_t exc_data_count) {
+ if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) {
+ DNBLogThreaded("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = "
+ "0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { 0x%llx, "
+ "0x%llx })",
+ __FUNCTION__, exc_port, thread_port, task_port, exc_type,
+ MachException::Name(exc_type), exc_data_count,
+ (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD),
+ (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD));
+ }
+
+ if (task_port == g_message->task_port) {
+ g_message->task_port = task_port;
+ g_message->thread_port = thread_port;
+ g_message->exc_type = exc_type;
+ g_message->exc_data.resize(exc_data_count);
+ ::memcpy(&g_message->exc_data[0], exc_data,
+ g_message->exc_data.size() * sizeof(mach_exception_data_type_t));
+ return KERN_SUCCESS;
+ }
+ return KERN_FAILURE;
+}
+
+void MachException::Message::Dump() const {
+ DNBLogThreadedIf(LOG_EXCEPTIONS, " exc_msg { bits = 0x%8.8x size = 0x%8.8x "
+ "remote-port = 0x%8.8x local-port = 0x%8.8x "
+ "reserved = 0x%8.8x id = 0x%8.8x } ",
+ exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size,
+ exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port,
+ exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id);
+
+ DNBLogThreadedIf(LOG_EXCEPTIONS, "reply_msg { bits = 0x%8.8x size = 0x%8.8x "
+ "remote-port = 0x%8.8x local-port = 0x%8.8x "
+ "reserved = 0x%8.8x id = 0x%8.8x }",
+ reply_msg.hdr.msgh_bits, reply_msg.hdr.msgh_size,
+ reply_msg.hdr.msgh_remote_port,
+ reply_msg.hdr.msgh_local_port, reply_msg.hdr.msgh_reserved,
+ reply_msg.hdr.msgh_id);
+
+ state.Dump();
+}
+
+bool MachException::Data::GetStopInfo(
+ struct DNBThreadStopInfo *stop_info) const {
+ // Zero out the structure.
+ memset(stop_info, 0, sizeof(struct DNBThreadStopInfo));
+ if (exc_type == 0) {
+ stop_info->reason = eStopTypeInvalid;
return true;
-}
-
-
-void
-MachException::Data::DumpStopReason() const
-{
- int soft_signal = SoftSignal();
- if (soft_signal)
- {
- const char *signal_str = SysSignal::Name(soft_signal);
- if (signal_str)
- DNBLog("signal(%s)", signal_str);
- else
- DNBLog("signal(%i)", soft_signal);
- return;
- }
- DNBLog("%s", Name(exc_type));
-}
-
-kern_return_t
-MachException::Message::Receive(mach_port_t port, mach_msg_option_t options, mach_msg_timeout_t timeout, mach_port_t notify_port)
-{
- DNBError err;
- const bool log_exceptions = DNBLogCheckLogBit(LOG_EXCEPTIONS);
- mach_msg_timeout_t mach_msg_timeout = options & MACH_RCV_TIMEOUT ? timeout : 0;
- if (log_exceptions && ((options & MACH_RCV_TIMEOUT) == 0))
- {
- // Dump this log message if we have no timeout in case it never returns
- DNBLogThreaded ("::mach_msg ( msg->{bits = %#x, size = %u remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = 0, rcv_size = %llu, rcv_name = %#x, timeout = %u, notify = %#x)",
- exc_msg.hdr.msgh_bits,
- exc_msg.hdr.msgh_size,
- exc_msg.hdr.msgh_remote_port,
- exc_msg.hdr.msgh_local_port,
- exc_msg.hdr.msgh_reserved,
- exc_msg.hdr.msgh_id,
- options,
- (uint64_t)sizeof (exc_msg.data),
- port,
- mach_msg_timeout,
- notify_port);
- }
+ }
- err = ::mach_msg (&exc_msg.hdr,
- options, // options
- 0, // Send size
- sizeof (exc_msg.data), // Receive size
- port, // exception port to watch for exception on
- mach_msg_timeout, // timeout in msec (obeyed only if MACH_RCV_TIMEOUT is ORed into the options parameter)
- notify_port);
-
- // Dump any errors we get
- if (log_exceptions)
- {
- err.LogThreaded("::mach_msg ( msg->{bits = %#x, size = %u remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = %u, rcv_size = %u, rcv_name = %#x, timeout = %u, notify = %#x)",
- exc_msg.hdr.msgh_bits,
- exc_msg.hdr.msgh_size,
- exc_msg.hdr.msgh_remote_port,
- exc_msg.hdr.msgh_local_port,
- exc_msg.hdr.msgh_reserved,
- exc_msg.hdr.msgh_id,
- options,
- 0,
- sizeof (exc_msg.data),
- port,
- mach_msg_timeout,
- notify_port);
- }
- return err.Error();
-}
-
-bool
-MachException::Message::CatchExceptionRaise(task_t task)
-{
- bool success = false;
- // locker will keep a mutex locked until it goes out of scope
-// PThreadMutex::Locker locker(&g_message_mutex);
- // DNBLogThreaded("calling mach_exc_server");
- state.task_port = task;
- g_message = &state;
- // The exc_server function is the MIG generated server handling function
- // to handle messages from the kernel relating to the occurrence of an
- // exception in a thread. Such messages are delivered to the exception port
- // set via thread_set_exception_ports or task_set_exception_ports. When an
- // exception occurs in a thread, the thread sends an exception message to
- // its exception port, blocking in the kernel waiting for the receipt of a
- // reply. The exc_server function performs all necessary argument handling
- // for this kernel message and calls catch_exception_raise,
- // catch_exception_raise_state or catch_exception_raise_state_identity,
- // which should handle the exception. If the called routine returns
- // KERN_SUCCESS, a reply message will be sent, allowing the thread to
- // continue from the point of the exception; otherwise, no reply message
- // is sent and the called routine must have dealt with the exception
- // thread directly.
- if (mach_exc_server (&exc_msg.hdr, &reply_msg.hdr))
- {
- success = true;
- }
- else if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
- {
- DNBLogThreaded("mach_exc_server returned zero...");
- }
- g_message = NULL;
- return success;
-}
-
-
-
-kern_return_t
-MachException::Message::Reply(MachProcess *process, int signal)
-{
- // Reply to the exception...
- DNBError err;
-
- // If we had a soft signal, we need to update the thread first so it can
- // continue without signaling
- int soft_signal = state.SoftSignal();
- if (soft_signal)
- {
- int state_pid = -1;
- if (process->Task().TaskPort() == state.task_port)
- {
- // This is our task, so we can update the signal to send to it
- state_pid = process->ProcessID();
- soft_signal = signal;
- }
- else
- {
- err = ::pid_for_task(state.task_port, &state_pid);
- }
-
- assert (state_pid != -1);
- if (state_pid != -1)
- {
- errno = 0;
- if (::ptrace (PT_THUPDATE, state_pid, (caddr_t)((uintptr_t)state.thread_port), soft_signal) != 0)
- err.SetError(errno, DNBError::POSIX);
- else
- err.Clear();
-
- if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail())
- err.LogThreaded("::ptrace (request = PT_THUPDATE, pid = 0x%4.4x, tid = 0x%4.4x, signal = %i)", state_pid, state.thread_port, soft_signal);
- }
- }
-
- DNBLogThreadedIf(LOG_EXCEPTIONS, "::mach_msg ( msg->{bits = %#x, size = %u, remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = %u, rcv_size = %u, rcv_name = %#x, timeout = %u, notify = %#x)",
- reply_msg.hdr.msgh_bits,
- reply_msg.hdr.msgh_size,
- reply_msg.hdr.msgh_remote_port,
- reply_msg.hdr.msgh_local_port,
- reply_msg.hdr.msgh_reserved,
- reply_msg.hdr.msgh_id,
- MACH_SEND_MSG | MACH_SEND_INTERRUPT,
- reply_msg.hdr.msgh_size,
- 0,
- MACH_PORT_NULL,
- MACH_MSG_TIMEOUT_NONE,
- MACH_PORT_NULL);
-
- err = ::mach_msg ( &reply_msg.hdr,
- MACH_SEND_MSG | MACH_SEND_INTERRUPT,
- reply_msg.hdr.msgh_size,
- 0,
- MACH_PORT_NULL,
- MACH_MSG_TIMEOUT_NONE,
- MACH_PORT_NULL);
-
- if (err.Fail())
- {
- if (err.Error() == MACH_SEND_INTERRUPTED)
- {
- if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
- err.LogThreaded("::mach_msg() - send interrupted");
- // TODO: keep retrying to reply???
- }
- else
- {
- if (state.task_port == process->Task().TaskPort())
- {
- DNBLogThreaded("error: mach_msg() returned an error when replying to a mach exception: error = %u", err.Error());
- }
- else
- {
- if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
- err.LogThreaded("::mach_msg() - failed (child of task)");
- }
- }
- }
-
- return err.Error();
-}
-
-
-void
-MachException::Data::Dump() const
-{
- const char *exc_type_name = MachException::Name(exc_type);
- DNBLogThreadedIf(LOG_EXCEPTIONS, " state { task_port = 0x%4.4x, thread_port = 0x%4.4x, exc_type = %i (%s) ...", task_port, thread_port, exc_type, exc_type_name ? exc_type_name : "???");
-
- const size_t exc_data_count = exc_data.size();
- // Dump any special exception data contents
- int soft_signal = SoftSignal();
- if (soft_signal != 0)
- {
- const char *sig_str = SysSignal::Name(soft_signal);
- DNBLogThreadedIf(LOG_EXCEPTIONS, " exc_data: EXC_SOFT_SIGNAL (%i (%s))", soft_signal, sig_str ? sig_str : "unknown signal");
- }
+ // We always stop with a mach exceptions
+ stop_info->reason = eStopTypeException;
+ // Save the EXC_XXXX exception type
+ stop_info->details.exception.type = exc_type;
+
+ // Fill in a text description
+ const char *exc_name = MachException::Name(exc_type);
+ char *desc = stop_info->description;
+ const char *end_desc = desc + DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH;
+ if (exc_name)
+ desc +=
+ snprintf(desc, DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH, "%s", exc_name);
+ else
+ desc +=
+ snprintf(desc, DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH, "%i", exc_type);
+
+ stop_info->details.exception.data_count = exc_data.size();
+
+ int soft_signal = SoftSignal();
+ if (soft_signal) {
+ if (desc < end_desc) {
+ const char *sig_str = SysSignal::Name(soft_signal);
+ snprintf(desc, end_desc - desc, " EXC_SOFT_SIGNAL( %i ( %s ))",
+ soft_signal, sig_str ? sig_str : "unknown signal");
+ }
+ } else {
+ // No special disassembly for exception data, just
+ size_t idx;
+ if (desc < end_desc) {
+ desc += snprintf(desc, end_desc - desc, " data[%llu] = {",
+ (uint64_t)stop_info->details.exception.data_count);
+
+ for (idx = 0;
+ desc < end_desc && idx < stop_info->details.exception.data_count;
+ ++idx)
+ desc += snprintf(
+ desc, end_desc - desc, "0x%llx%c", (uint64_t)exc_data[idx],
+ ((idx + 1 == stop_info->details.exception.data_count) ? '}' : ','));
+ }
+ }
+
+ // Copy the exception data
+ size_t i;
+ for (i = 0; i < stop_info->details.exception.data_count; i++)
+ stop_info->details.exception.data[i] = exc_data[i];
+
+ return true;
+}
+
+void MachException::Data::DumpStopReason() const {
+ int soft_signal = SoftSignal();
+ if (soft_signal) {
+ const char *signal_str = SysSignal::Name(soft_signal);
+ if (signal_str)
+ DNBLog("signal(%s)", signal_str);
else
- {
- // No special disassembly for this data, just dump the data
- size_t idx;
- for (idx = 0; idx < exc_data_count; ++idx)
- {
- DNBLogThreadedIf(LOG_EXCEPTIONS, " exc_data[%llu]: 0x%llx", (uint64_t)idx, (uint64_t)exc_data[idx]);
- }
- }
-}
-
-#define PREV_EXC_MASK_ALL (EXC_MASK_BAD_ACCESS | \
- EXC_MASK_BAD_INSTRUCTION | \
- EXC_MASK_ARITHMETIC | \
- EXC_MASK_EMULATION | \
- EXC_MASK_SOFTWARE | \
- EXC_MASK_BREAKPOINT | \
- EXC_MASK_SYSCALL | \
- EXC_MASK_MACH_SYSCALL | \
- EXC_MASK_RPC_ALERT | \
- EXC_MASK_MACHINE)
+ DNBLog("signal(%i)", soft_signal);
+ return;
+ }
+ DNBLog("%s", Name(exc_type));
+}
+
+kern_return_t MachException::Message::Receive(mach_port_t port,
+ mach_msg_option_t options,
+ mach_msg_timeout_t timeout,
+ mach_port_t notify_port) {
+ DNBError err;
+ const bool log_exceptions = DNBLogCheckLogBit(LOG_EXCEPTIONS);
+ mach_msg_timeout_t mach_msg_timeout =
+ options & MACH_RCV_TIMEOUT ? timeout : 0;
+ if (log_exceptions && ((options & MACH_RCV_TIMEOUT) == 0)) {
+ // Dump this log message if we have no timeout in case it never returns
+ DNBLogThreaded("::mach_msg ( msg->{bits = %#x, size = %u remote_port = "
+ "%#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option "
+ "= %#x, send_size = 0, rcv_size = %llu, rcv_name = %#x, "
+ "timeout = %u, notify = %#x)",
+ exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size,
+ exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port,
+ exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options,
+ (uint64_t)sizeof(exc_msg.data), port, mach_msg_timeout,
+ notify_port);
+ }
+
+ err = ::mach_msg(&exc_msg.hdr,
+ options, // options
+ 0, // Send size
+ sizeof(exc_msg.data), // Receive size
+ port, // exception port to watch for exception on
+ mach_msg_timeout, // timeout in msec (obeyed only if
+ // MACH_RCV_TIMEOUT is ORed into the
+ // options parameter)
+ notify_port);
+
+ // Dump any errors we get
+ if (log_exceptions) {
+ err.LogThreaded("::mach_msg ( msg->{bits = %#x, size = %u remote_port = "
+ "%#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, "
+ "option = %#x, send_size = %u, rcv_size = %u, rcv_name = "
+ "%#x, timeout = %u, notify = %#x)",
+ exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size,
+ exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port,
+ exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0,
+ sizeof(exc_msg.data), port, mach_msg_timeout, notify_port);
+ }
+ return err.Error();
+}
+
+bool MachException::Message::CatchExceptionRaise(task_t task) {
+ bool success = false;
+ // locker will keep a mutex locked until it goes out of scope
+ // PThreadMutex::Locker locker(&g_message_mutex);
+ // DNBLogThreaded("calling mach_exc_server");
+ state.task_port = task;
+ g_message = &state;
+ // The exc_server function is the MIG generated server handling function
+ // to handle messages from the kernel relating to the occurrence of an
+ // exception in a thread. Such messages are delivered to the exception port
+ // set via thread_set_exception_ports or task_set_exception_ports. When an
+ // exception occurs in a thread, the thread sends an exception message to
+ // its exception port, blocking in the kernel waiting for the receipt of a
+ // reply. The exc_server function performs all necessary argument handling
+ // for this kernel message and calls catch_exception_raise,
+ // catch_exception_raise_state or catch_exception_raise_state_identity,
+ // which should handle the exception. If the called routine returns
+ // KERN_SUCCESS, a reply message will be sent, allowing the thread to
+ // continue from the point of the exception; otherwise, no reply message
+ // is sent and the called routine must have dealt with the exception
+ // thread directly.
+ if (mach_exc_server(&exc_msg.hdr, &reply_msg.hdr)) {
+ success = true;
+ } else if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) {
+ DNBLogThreaded("mach_exc_server returned zero...");
+ }
+ g_message = NULL;
+ return success;
+}
+
+kern_return_t MachException::Message::Reply(MachProcess *process, int signal) {
+ // Reply to the exception...
+ DNBError err;
+
+ // If we had a soft signal, we need to update the thread first so it can
+ // continue without signaling
+ int soft_signal = state.SoftSignal();
+ if (soft_signal) {
+ int state_pid = -1;
+ if (process->Task().TaskPort() == state.task_port) {
+ // This is our task, so we can update the signal to send to it
+ state_pid = process->ProcessID();
+ soft_signal = signal;
+ } else {
+ err = ::pid_for_task(state.task_port, &state_pid);
+ }
+
+ assert(state_pid != -1);
+ if (state_pid != -1) {
+ errno = 0;
+ if (::ptrace(PT_THUPDATE, state_pid,
+ (caddr_t)((uintptr_t)state.thread_port), soft_signal) != 0)
+ err.SetError(errno, DNBError::POSIX);
+ else
+ err.Clear();
+
+ if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail())
+ err.LogThreaded("::ptrace (request = PT_THUPDATE, pid = 0x%4.4x, tid = "
+ "0x%4.4x, signal = %i)",
+ state_pid, state.thread_port, soft_signal);
+ }
+ }
+
+ DNBLogThreadedIf(
+ LOG_EXCEPTIONS, "::mach_msg ( msg->{bits = %#x, size = %u, remote_port = "
+ "%#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, "
+ "option = %#x, send_size = %u, rcv_size = %u, rcv_name = "
+ "%#x, timeout = %u, notify = %#x)",
+ reply_msg.hdr.msgh_bits, reply_msg.hdr.msgh_size,
+ reply_msg.hdr.msgh_remote_port, reply_msg.hdr.msgh_local_port,
+ reply_msg.hdr.msgh_reserved, reply_msg.hdr.msgh_id,
+ MACH_SEND_MSG | MACH_SEND_INTERRUPT, reply_msg.hdr.msgh_size, 0,
+ MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ err = ::mach_msg(&reply_msg.hdr, MACH_SEND_MSG | MACH_SEND_INTERRUPT,
+ reply_msg.hdr.msgh_size, 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ if (err.Fail()) {
+ if (err.Error() == MACH_SEND_INTERRUPTED) {
+ if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
+ err.LogThreaded("::mach_msg() - send interrupted");
+ // TODO: keep retrying to reply???
+ } else {
+ if (state.task_port == process->Task().TaskPort()) {
+ DNBLogThreaded("error: mach_msg() returned an error when replying to a "
+ "mach exception: error = %u",
+ err.Error());
+ } else {
+ if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
+ err.LogThreaded("::mach_msg() - failed (child of task)");
+ }
+ }
+ }
+
+ return err.Error();
+}
+
+void MachException::Data::Dump() const {
+ const char *exc_type_name = MachException::Name(exc_type);
+ DNBLogThreadedIf(
+ LOG_EXCEPTIONS, " state { task_port = 0x%4.4x, thread_port = "
+ "0x%4.4x, exc_type = %i (%s) ...",
+ task_port, thread_port, exc_type, exc_type_name ? exc_type_name : "???");
+
+ const size_t exc_data_count = exc_data.size();
+ // Dump any special exception data contents
+ int soft_signal = SoftSignal();
+ if (soft_signal != 0) {
+ const char *sig_str = SysSignal::Name(soft_signal);
+ DNBLogThreadedIf(LOG_EXCEPTIONS,
+ " exc_data: EXC_SOFT_SIGNAL (%i (%s))",
+ soft_signal, sig_str ? sig_str : "unknown signal");
+ } else {
+ // No special disassembly for this data, just dump the data
+ size_t idx;
+ for (idx = 0; idx < exc_data_count; ++idx) {
+ DNBLogThreadedIf(LOG_EXCEPTIONS, " exc_data[%llu]: 0x%llx",
+ (uint64_t)idx, (uint64_t)exc_data[idx]);
+ }
+ }
+}
+
+#define PREV_EXC_MASK_ALL \
+ (EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | \
+ EXC_MASK_EMULATION | EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT | \
+ EXC_MASK_SYSCALL | EXC_MASK_MACH_SYSCALL | EXC_MASK_RPC_ALERT | \
+ EXC_MASK_MACHINE)
-// Don't listen for EXC_RESOURCE, it should really get handled by the system handler.
+// Don't listen for EXC_RESOURCE, it should really get handled by the system
+// handler.
#ifndef EXC_RESOURCE
#define EXC_RESOURCE 11
@@ -497,85 +397,92 @@ MachException::Data::Dump() const
#define LLDB_EXC_MASK (EXC_MASK_ALL & ~EXC_MASK_RESOURCE)
-kern_return_t
-MachException::PortInfo::Save (task_t task)
-{
- DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE, "MachException::PortInfo::Save ( task = 0x%4.4x )", task);
- // Be careful to be able to have debugserver built on a newer OS than what
- // it is currently running on by being able to start with all exceptions
- // and back off to just what is supported on the current system
- DNBError err;
-
- mask = LLDB_EXC_MASK;
-
- count = (sizeof (ports) / sizeof (ports[0]));
- err = ::task_get_exception_ports (task, mask, masks, &count, ports, behaviors, flavors);
+kern_return_t MachException::PortInfo::Save(task_t task) {
+ DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE,
+ "MachException::PortInfo::Save ( task = 0x%4.4x )", task);
+ // Be careful to be able to have debugserver built on a newer OS than what
+ // it is currently running on by being able to start with all exceptions
+ // and back off to just what is supported on the current system
+ DNBError err;
+
+ mask = LLDB_EXC_MASK;
+
+ count = (sizeof(ports) / sizeof(ports[0]));
+ err = ::task_get_exception_ports(task, mask, masks, &count, ports, behaviors,
+ flavors);
+ if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail())
+ err.LogThreaded("::task_get_exception_ports ( task = 0x%4.4x, mask = 0x%x, "
+ "maskCnt => %u, ports, behaviors, flavors )",
+ task, mask, count);
+
+ if (err.Error() == KERN_INVALID_ARGUMENT && mask != PREV_EXC_MASK_ALL) {
+ mask = PREV_EXC_MASK_ALL;
+ count = (sizeof(ports) / sizeof(ports[0]));
+ err = ::task_get_exception_ports(task, mask, masks, &count, ports,
+ behaviors, flavors);
if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail())
- err.LogThreaded("::task_get_exception_ports ( task = 0x%4.4x, mask = 0x%x, maskCnt => %u, ports, behaviors, flavors )", task, mask, count);
-
- if (err.Error() == KERN_INVALID_ARGUMENT && mask != PREV_EXC_MASK_ALL)
- {
- mask = PREV_EXC_MASK_ALL;
- count = (sizeof (ports) / sizeof (ports[0]));
- err = ::task_get_exception_ports (task, mask, masks, &count, ports, behaviors, flavors);
- if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail())
- err.LogThreaded("::task_get_exception_ports ( task = 0x%4.4x, mask = 0x%x, maskCnt => %u, ports, behaviors, flavors )", task, mask, count);
- }
- if (err.Fail())
- {
- mask = 0;
- count = 0;
- }
- return err.Error();
-}
-
-kern_return_t
-MachException::PortInfo::Restore (task_t task)
-{
- DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE, "MachException::PortInfo::Restore( task = 0x%4.4x )", task);
- uint32_t i = 0;
- DNBError err;
- if (count > 0)
- {
- for (i = 0; i < count; i++)
- {
- err = ::task_set_exception_ports (task, masks[i], ports[i], behaviors[i], flavors[i]);
- if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail())
- {
- err.LogThreaded("::task_set_exception_ports ( task = 0x%4.4x, exception_mask = 0x%8.8x, new_port = 0x%4.4x, behavior = 0x%8.8x, new_flavor = 0x%8.8x )", task, masks[i], ports[i], behaviors[i], flavors[i]);
- // Bail if we encounter any errors
- }
-
- if (err.Fail())
- break;
- }
- }
+ err.LogThreaded("::task_get_exception_ports ( task = 0x%4.4x, mask = "
+ "0x%x, maskCnt => %u, ports, behaviors, flavors )",
+ task, mask, count);
+ }
+ if (err.Fail()) {
+ mask = 0;
count = 0;
- return err.Error();
+ }
+ return err.Error();
}
-const char *
-MachException::Name(exception_type_t exc_type)
-{
- switch (exc_type)
- {
- case EXC_BAD_ACCESS: return "EXC_BAD_ACCESS";
- case EXC_BAD_INSTRUCTION: return "EXC_BAD_INSTRUCTION";
- case EXC_ARITHMETIC: return "EXC_ARITHMETIC";
- case EXC_EMULATION: return "EXC_EMULATION";
- case EXC_SOFTWARE: return "EXC_SOFTWARE";
- case EXC_BREAKPOINT: return "EXC_BREAKPOINT";
- case EXC_SYSCALL: return "EXC_SYSCALL";
- case EXC_MACH_SYSCALL: return "EXC_MACH_SYSCALL";
- case EXC_RPC_ALERT: return "EXC_RPC_ALERT";
-#ifdef EXC_CRASH
- case EXC_CRASH: return "EXC_CRASH";
-#endif
- default:
+kern_return_t MachException::PortInfo::Restore(task_t task) {
+ DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE,
+ "MachException::PortInfo::Restore( task = 0x%4.4x )", task);
+ uint32_t i = 0;
+ DNBError err;
+ if (count > 0) {
+ for (i = 0; i < count; i++) {
+ err = ::task_set_exception_ports(task, masks[i], ports[i], behaviors[i],
+ flavors[i]);
+ if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) {
+ err.LogThreaded("::task_set_exception_ports ( task = 0x%4.4x, "
+ "exception_mask = 0x%8.8x, new_port = 0x%4.4x, "
+ "behavior = 0x%8.8x, new_flavor = 0x%8.8x )",
+ task, masks[i], ports[i], behaviors[i], flavors[i]);
+ // Bail if we encounter any errors
+ }
+
+ if (err.Fail())
break;
}
- return NULL;
+ }
+ count = 0;
+ return err.Error();
+}
+
+const char *MachException::Name(exception_type_t exc_type) {
+ switch (exc_type) {
+ case EXC_BAD_ACCESS:
+ return "EXC_BAD_ACCESS";
+ case EXC_BAD_INSTRUCTION:
+ return "EXC_BAD_INSTRUCTION";
+ case EXC_ARITHMETIC:
+ return "EXC_ARITHMETIC";
+ case EXC_EMULATION:
+ return "EXC_EMULATION";
+ case EXC_SOFTWARE:
+ return "EXC_SOFTWARE";
+ case EXC_BREAKPOINT:
+ return "EXC_BREAKPOINT";
+ case EXC_SYSCALL:
+ return "EXC_SYSCALL";
+ case EXC_MACH_SYSCALL:
+ return "EXC_MACH_SYSCALL";
+ case EXC_RPC_ALERT:
+ return "EXC_RPC_ALERT";
+#ifdef EXC_CRASH
+ case EXC_CRASH:
+ return "EXC_CRASH";
+#endif
+ default:
+ break;
+ }
+ return NULL;
}
-
-
-
Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachException.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachException.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachException.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachException.h Tue Sep 6 15:57:50 2016
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef __MachException_h__
#define __MachException_h__
@@ -21,113 +20,105 @@
class MachProcess;
class PThreadMutex;
-typedef union MachMessageTag
-{
- mach_msg_header_t hdr;
- char data[1024];
+typedef union MachMessageTag {
+ mach_msg_header_t hdr;
+ char data[1024];
} MachMessage;
-
-class MachException
-{
+class MachException {
public:
-
- struct PortInfo
- {
- exception_mask_t mask; // the exception mask for this device which may be a subset of EXC_MASK_ALL...
- exception_mask_t masks[EXC_TYPES_COUNT];
- mach_port_t ports[EXC_TYPES_COUNT];
- exception_behavior_t behaviors[EXC_TYPES_COUNT];
- thread_state_flavor_t flavors[EXC_TYPES_COUNT];
- mach_msg_type_number_t count;
-
- kern_return_t Save(task_t task);
- kern_return_t Restore(task_t task);
- };
-
- struct Data
- {
- task_t task_port;
- thread_t thread_port;
- exception_type_t exc_type;
- std::vector<mach_exception_data_type_t> exc_data;
- Data() :
- task_port(TASK_NULL),
- thread_port(THREAD_NULL),
- exc_type(0),
- exc_data()
- {
- }
-
- void Clear()
- {
- task_port = TASK_NULL;
- thread_port = THREAD_NULL;
- exc_type = 0;
- exc_data.clear();
- }
- bool IsValid() const
- {
- return task_port != TASK_NULL &&
- thread_port != THREAD_NULL &&
- exc_type != 0;
- }
- // Return the SoftSignal for this MachException data, or zero if there is none
- int SoftSignal() const
- {
- if (exc_type == EXC_SOFTWARE && exc_data.size() == 2 && exc_data[0] == EXC_SOFT_SIGNAL)
- return static_cast<int>(exc_data[1]);
- return 0;
- }
- bool IsBreakpoint() const
- {
- return (exc_type == EXC_BREAKPOINT || ((exc_type == EXC_SOFTWARE) && exc_data[0] == 1));
- }
- void Dump() const;
- void DumpStopReason() const;
- bool GetStopInfo(struct DNBThreadStopInfo *stop_info) const;
- };
-
- struct Message
- {
- MachMessage exc_msg;
- MachMessage reply_msg;
- Data state;
-
- Message() :
- state()
- {
- memset(&exc_msg, 0, sizeof(exc_msg));
- memset(&reply_msg, 0, sizeof(reply_msg));
- }
- bool CatchExceptionRaise(task_t task);
- void Dump() const;
- kern_return_t Reply (MachProcess *process, int signal);
- kern_return_t Receive( mach_port_t receive_port,
- mach_msg_option_t options,
- mach_msg_timeout_t timeout,
- mach_port_t notify_port = MACH_PORT_NULL);
-
- typedef std::vector<Message> collection;
- typedef collection::iterator iterator;
- typedef collection::const_iterator const_iterator;
- };
-
- enum
- {
- e_actionForward, // Forward signal to inferior process
- e_actionStop, // Stop when this signal is received
- };
- struct Action
- {
- task_t task_port; // Set to TASK_NULL for any TASK
- thread_t thread_port; // Set to THREAD_NULL for any thread
- exception_type_t exc_mask; // Mach exception mask to watch for
- std::vector<mach_exception_data_type_t> exc_data_mask; // Mask to apply to exception data, or empty to ignore exc_data value for exception
- std::vector<mach_exception_data_type_t> exc_data_value; // Value to compare to exception data after masking, or empty to ignore exc_data value for exception
- uint8_t flags; // Action flags describing what to do with the exception
- };
- static const char *Name(exception_type_t exc_type);
+ struct PortInfo {
+ exception_mask_t mask; // the exception mask for this device which may be a
+ // subset of EXC_MASK_ALL...
+ exception_mask_t masks[EXC_TYPES_COUNT];
+ mach_port_t ports[EXC_TYPES_COUNT];
+ exception_behavior_t behaviors[EXC_TYPES_COUNT];
+ thread_state_flavor_t flavors[EXC_TYPES_COUNT];
+ mach_msg_type_number_t count;
+
+ kern_return_t Save(task_t task);
+ kern_return_t Restore(task_t task);
+ };
+
+ struct Data {
+ task_t task_port;
+ thread_t thread_port;
+ exception_type_t exc_type;
+ std::vector<mach_exception_data_type_t> exc_data;
+ Data()
+ : task_port(TASK_NULL), thread_port(THREAD_NULL), exc_type(0),
+ exc_data() {}
+
+ void Clear() {
+ task_port = TASK_NULL;
+ thread_port = THREAD_NULL;
+ exc_type = 0;
+ exc_data.clear();
+ }
+ bool IsValid() const {
+ return task_port != TASK_NULL && thread_port != THREAD_NULL &&
+ exc_type != 0;
+ }
+ // Return the SoftSignal for this MachException data, or zero if there is
+ // none
+ int SoftSignal() const {
+ if (exc_type == EXC_SOFTWARE && exc_data.size() == 2 &&
+ exc_data[0] == EXC_SOFT_SIGNAL)
+ return static_cast<int>(exc_data[1]);
+ return 0;
+ }
+ bool IsBreakpoint() const {
+ return (exc_type == EXC_BREAKPOINT ||
+ ((exc_type == EXC_SOFTWARE) && exc_data[0] == 1));
+ }
+ void Dump() const;
+ void DumpStopReason() const;
+ bool GetStopInfo(struct DNBThreadStopInfo *stop_info) const;
+ };
+
+ struct Message {
+ MachMessage exc_msg;
+ MachMessage reply_msg;
+ Data state;
+
+ Message() : state() {
+ memset(&exc_msg, 0, sizeof(exc_msg));
+ memset(&reply_msg, 0, sizeof(reply_msg));
+ }
+ bool CatchExceptionRaise(task_t task);
+ void Dump() const;
+ kern_return_t Reply(MachProcess *process, int signal);
+ kern_return_t Receive(mach_port_t receive_port, mach_msg_option_t options,
+ mach_msg_timeout_t timeout,
+ mach_port_t notify_port = MACH_PORT_NULL);
+
+ typedef std::vector<Message> collection;
+ typedef collection::iterator iterator;
+ typedef collection::const_iterator const_iterator;
+ };
+
+ enum {
+ e_actionForward, // Forward signal to inferior process
+ e_actionStop, // Stop when this signal is received
+ };
+ struct Action {
+ task_t task_port; // Set to TASK_NULL for any TASK
+ thread_t thread_port; // Set to THREAD_NULL for any thread
+ exception_type_t exc_mask; // Mach exception mask to watch for
+ std::vector<mach_exception_data_type_t> exc_data_mask; // Mask to apply to
+ // exception data, or
+ // empty to ignore
+ // exc_data value for
+ // exception
+ std::vector<mach_exception_data_type_t> exc_data_value; // Value to compare
+ // to exception data
+ // after masking, or
+ // empty to ignore
+ // exc_data value
+ // for exception
+ uint8_t flags; // Action flags describing what to do with the exception
+ };
+ static const char *Name(exception_type_t exc_type);
};
#endif
Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.h Tue Sep 6 15:57:50 2016
@@ -14,405 +14,432 @@
#ifndef __MachProcess_h__
#define __MachProcess_h__
-#include <mach/mach.h>
+#include <CoreFoundation/CoreFoundation.h>
#include <mach-o/loader.h>
-#include <sys/signal.h>
+#include <mach/mach.h>
#include <pthread.h>
+#include <sys/signal.h>
#include <uuid/uuid.h>
#include <vector>
-#include <CoreFoundation/CoreFoundation.h>
-#include "DNBDefs.h"
#include "DNBBreakpoint.h"
+#include "DNBDefs.h"
#include "DNBError.h"
#include "DNBThreadResumeActions.h"
+#include "Genealogy.h"
+#include "JSONGenerator.h"
#include "MachException.h"
-#include "MachVMMemory.h"
#include "MachTask.h"
#include "MachThreadList.h"
+#include "MachVMMemory.h"
#include "PThreadCondition.h"
#include "PThreadEvent.h"
#include "PThreadMutex.h"
-#include "Genealogy.h"
#include "ThreadInfo.h"
-#include "JSONGenerator.h"
class DNBThreadResumeActions;
-class MachProcess
-{
+class MachProcess {
public:
- //----------------------------------------------------------------------
- // Constructors and Destructors
- //----------------------------------------------------------------------
- MachProcess ();
- ~MachProcess ();
-
- // A structure that can hold everything debugserver needs to know from
- // a binary's Mach-O header / load commands.
-
- struct mach_o_segment
- {
- std::string name;
- uint64_t vmaddr;
- uint64_t vmsize;
- uint64_t fileoff;
- uint64_t filesize;
- uint64_t maxprot;
- uint64_t initprot;
- uint64_t nsects;
- uint64_t flags;
- };
-
- struct mach_o_information
- {
- struct mach_header_64 mach_header;
- std::vector<struct mach_o_segment> segments;
- uuid_t uuid;
- std::string min_version_os_name;
- std::string min_version_os_version;
- };
-
- struct binary_image_information
- {
- std::string filename;
- uint64_t load_address;
- uint64_t mod_date; // may not be available - 0 if so
- struct mach_o_information macho_info;
-
- binary_image_information () :
- filename (),
- load_address (INVALID_NUB_ADDRESS),
- mod_date (0)
- { }
- };
-
- //----------------------------------------------------------------------
- // Child process control
- //----------------------------------------------------------------------
- pid_t AttachForDebug (pid_t pid, char *err_str, size_t err_len);
- pid_t LaunchForDebug (const char *path,
- char const *argv[],
- char const *envp[],
- const char *working_directory,
- const char *stdin_path,
- const char *stdout_path,
- const char *stderr_path,
- bool no_stdio,
- nub_launch_flavor_t launch_flavor,
- int disable_aslr,
- const char *event_data,
- DNBError &err);
-
- static uint32_t GetCPUTypeForLocalProcess (pid_t pid);
- static pid_t ForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], MachProcess* process, DNBError &err);
- static pid_t PosixSpawnChildForPTraceDebugging (const char *path,
- cpu_type_t cpu_type,
- char const *argv[],
- char const *envp[],
- const char *working_directory,
- const char *stdin_path,
- const char *stdout_path,
- const char *stderr_path,
- bool no_stdio,
- MachProcess* process,
- int disable_aslr,
- DNBError& err);
- nub_addr_t GetDYLDAllImageInfosAddress ();
- static const void * PrepareForAttach (const char *path, nub_launch_flavor_t launch_flavor, bool waitfor, DNBError &err_str);
- static void CleanupAfterAttach (const void *attach_token, nub_launch_flavor_t launch_flavor, bool success, DNBError &err_str);
- static nub_process_t CheckForProcess (const void *attach_token, nub_launch_flavor_t launch_flavor);
+ //----------------------------------------------------------------------
+ // Constructors and Destructors
+ //----------------------------------------------------------------------
+ MachProcess();
+ ~MachProcess();
+
+ // A structure that can hold everything debugserver needs to know from
+ // a binary's Mach-O header / load commands.
+
+ struct mach_o_segment {
+ std::string name;
+ uint64_t vmaddr;
+ uint64_t vmsize;
+ uint64_t fileoff;
+ uint64_t filesize;
+ uint64_t maxprot;
+ uint64_t initprot;
+ uint64_t nsects;
+ uint64_t flags;
+ };
+
+ struct mach_o_information {
+ struct mach_header_64 mach_header;
+ std::vector<struct mach_o_segment> segments;
+ uuid_t uuid;
+ std::string min_version_os_name;
+ std::string min_version_os_version;
+ };
+
+ struct binary_image_information {
+ std::string filename;
+ uint64_t load_address;
+ uint64_t mod_date; // may not be available - 0 if so
+ struct mach_o_information macho_info;
+
+ binary_image_information()
+ : filename(), load_address(INVALID_NUB_ADDRESS), mod_date(0) {}
+ };
+
+ //----------------------------------------------------------------------
+ // Child process control
+ //----------------------------------------------------------------------
+ pid_t AttachForDebug(pid_t pid, char *err_str, size_t err_len);
+ pid_t LaunchForDebug(const char *path, char const *argv[], char const *envp[],
+ const char *working_directory, const char *stdin_path,
+ const char *stdout_path, const char *stderr_path,
+ bool no_stdio, nub_launch_flavor_t launch_flavor,
+ int disable_aslr, const char *event_data, DNBError &err);
+
+ static uint32_t GetCPUTypeForLocalProcess(pid_t pid);
+ static pid_t ForkChildForPTraceDebugging(const char *path, char const *argv[],
+ char const *envp[],
+ MachProcess *process, DNBError &err);
+ static pid_t PosixSpawnChildForPTraceDebugging(
+ const char *path, cpu_type_t cpu_type, char const *argv[],
+ char const *envp[], const char *working_directory, const char *stdin_path,
+ const char *stdout_path, const char *stderr_path, bool no_stdio,
+ MachProcess *process, int disable_aslr, DNBError &err);
+ nub_addr_t GetDYLDAllImageInfosAddress();
+ static const void *PrepareForAttach(const char *path,
+ nub_launch_flavor_t launch_flavor,
+ bool waitfor, DNBError &err_str);
+ static void CleanupAfterAttach(const void *attach_token,
+ nub_launch_flavor_t launch_flavor,
+ bool success, DNBError &err_str);
+ static nub_process_t CheckForProcess(const void *attach_token,
+ nub_launch_flavor_t launch_flavor);
#if defined(WITH_BKS) || defined(WITH_FBS)
- pid_t BoardServiceLaunchForDebug (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err);
- pid_t BoardServiceForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err);
- bool BoardServiceSendEvent (const char *event, DNBError &error);
+ pid_t BoardServiceLaunchForDebug(const char *app_bundle_path,
+ char const *argv[], char const *envp[],
+ bool no_stdio, bool disable_aslr,
+ const char *event_data,
+ DNBError &launch_err);
+ pid_t BoardServiceForkChildForPTraceDebugging(
+ const char *path, char const *argv[], char const *envp[], bool no_stdio,
+ bool disable_aslr, const char *event_data, DNBError &launch_err);
+ bool BoardServiceSendEvent(const char *event, DNBError &error);
#endif
- static bool GetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch);
+ static bool GetOSVersionNumbers(uint64_t *major, uint64_t *minor,
+ uint64_t *patch);
#ifdef WITH_BKS
- static void BKSCleanupAfterAttach (const void *attach_token, DNBError &err_str);
+ static void BKSCleanupAfterAttach(const void *attach_token,
+ DNBError &err_str);
#endif // WITH_BKS
#ifdef WITH_FBS
- static void FBSCleanupAfterAttach (const void *attach_token, DNBError &err_str);
-#endif // WITH_FBS
+ static void FBSCleanupAfterAttach(const void *attach_token,
+ DNBError &err_str);
+#endif // WITH_FBS
#ifdef WITH_SPRINGBOARD
- pid_t SBLaunchForDebug (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, DNBError &launch_err);
- static pid_t SBForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], bool no_stdio, MachProcess* process, DNBError &launch_err);
-#endif // WITH_SPRINGBOARD
- nub_addr_t LookupSymbol (const char *name, const char *shlib);
- void SetNameToAddressCallback (DNBCallbackNameToAddress callback, void *baton)
- {
- m_name_to_addr_callback = callback;
- m_name_to_addr_baton = baton;
- }
- void SetSharedLibraryInfoCallback (DNBCallbackCopyExecutableImageInfos callback, void *baton)
- {
- m_image_infos_callback = callback;
- m_image_infos_baton = baton;
- }
-
- bool Resume (const DNBThreadResumeActions& thread_actions);
- bool Signal (int signal, const struct timespec *timeout_abstime = NULL);
- bool Interrupt();
- bool SendEvent (const char *event, DNBError &send_err);
- bool Kill (const struct timespec *timeout_abstime = NULL);
- bool Detach ();
- nub_size_t ReadMemory (nub_addr_t addr, nub_size_t size, void *buf);
- nub_size_t WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf);
-
- //----------------------------------------------------------------------
- // Path and arg accessors
- //----------------------------------------------------------------------
- const char * Path () const { return m_path.c_str(); }
- size_t ArgumentCount () const { return m_args.size(); }
- const char * ArgumentAtIndex (size_t arg_idx) const
- {
- if (arg_idx < m_args.size())
- return m_args[arg_idx].c_str();
- return NULL;
- }
-
- //----------------------------------------------------------------------
- // Breakpoint functions
- //----------------------------------------------------------------------
- DNBBreakpoint * CreateBreakpoint (nub_addr_t addr, nub_size_t length, bool hardware);
- bool DisableBreakpoint (nub_addr_t addr, bool remove);
- void DisableAllBreakpoints (bool remove);
- bool EnableBreakpoint (nub_addr_t addr);
- DNBBreakpointList& Breakpoints() { return m_breakpoints; }
- const DNBBreakpointList& Breakpoints() const { return m_breakpoints; }
-
- //----------------------------------------------------------------------
- // Watchpoint functions
- //----------------------------------------------------------------------
- DNBBreakpoint * CreateWatchpoint (nub_addr_t addr, nub_size_t length, uint32_t watch_type, bool hardware);
- bool DisableWatchpoint (nub_addr_t addr, bool remove);
- void DisableAllWatchpoints (bool remove);
- bool EnableWatchpoint (nub_addr_t addr);
- uint32_t GetNumSupportedHardwareWatchpoints () const;
- DNBBreakpointList& Watchpoints() { return m_watchpoints; }
- const DNBBreakpointList& Watchpoints() const { return m_watchpoints; }
-
- //----------------------------------------------------------------------
- // Exception thread functions
- //----------------------------------------------------------------------
- bool StartSTDIOThread ();
- static void * STDIOThread (void *arg);
- void ExceptionMessageReceived (const MachException::Message& exceptionMessage);
- task_t ExceptionMessageBundleComplete ();
- void SharedLibrariesUpdated ();
- nub_size_t CopyImageInfos (struct DNBExecutableImageInfo **image_infos, bool only_changed);
-
- //----------------------------------------------------------------------
- // Profile functions
- //----------------------------------------------------------------------
- void SetEnableAsyncProfiling (bool enable, uint64_t internal_usec, DNBProfileDataScanType scan_type);
- bool IsProfilingEnabled () { return m_profile_enabled; }
- useconds_t ProfileInterval () { return m_profile_interval_usec; }
- bool StartProfileThread ();
- static void * ProfileThread (void *arg);
- void SignalAsyncProfileData (const char *info);
- size_t GetAsyncProfileData (char *buf, size_t buf_size);
-
- //----------------------------------------------------------------------
- // Accessors
- //----------------------------------------------------------------------
- pid_t ProcessID () const { return m_pid; }
- bool ProcessIDIsValid () const { return m_pid > 0; }
- pid_t SetProcessID (pid_t pid);
- MachTask& Task() { return m_task; }
- const MachTask& Task() const { return m_task; }
-
- PThreadEvent& Events() { return m_events; }
- const DNBRegisterSetInfo *
- GetRegisterSetInfo (nub_thread_t tid, nub_size_t *num_reg_sets) const;
- bool GetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value) const;
- bool SetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value) const;
- nub_bool_t SyncThreadState (nub_thread_t tid);
- const char * ThreadGetName (nub_thread_t tid);
- nub_state_t ThreadGetState (nub_thread_t tid);
- ThreadInfo::QoS GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index);
- nub_addr_t GetPThreadT (nub_thread_t tid);
- nub_addr_t GetDispatchQueueT (nub_thread_t tid);
- nub_addr_t GetTSDAddressForThread (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);
-
-
- bool GetMachOInformationFromMemory (nub_addr_t mach_o_header_addr, int wordsize, struct mach_o_information &inf);
- JSONGenerator::ObjectSP FormatDynamicLibrariesIntoJSON (const std::vector<struct binary_image_information> &image_infos);
- void GetAllLoadedBinariesViaDYLDSPI (std::vector<struct binary_image_information> &image_infos);
- JSONGenerator::ObjectSP GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count);
- JSONGenerator::ObjectSP GetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses);
- JSONGenerator::ObjectSP GetAllLoadedLibrariesInfos (nub_process_t pid);
- JSONGenerator::ObjectSP GetSharedCacheInfo (nub_process_t pid);
-
- nub_size_t GetNumThreads () const;
- nub_thread_t GetThreadAtIndex (nub_size_t thread_idx) const;
- nub_thread_t GetCurrentThread ();
- nub_thread_t GetCurrentThreadMachPort ();
- nub_thread_t SetCurrentThread (nub_thread_t tid);
- MachThreadList & GetThreadList() { return m_thread_list; }
- bool GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info);
- void DumpThreadStoppedReason(nub_thread_t tid) const;
- const char * GetThreadInfo (nub_thread_t tid) const;
-
- nub_thread_t GetThreadIDForMachPortNumber (thread_t mach_port_number) const;
-
- uint32_t GetCPUType ();
- nub_state_t GetState ();
- void SetState (nub_state_t state);
- bool IsRunning (nub_state_t state)
- {
- return state == eStateRunning || IsStepping(state);
- }
- bool IsStepping (nub_state_t state)
- {
- return state == eStateStepping;
- }
- bool CanResume (nub_state_t state)
- {
- return state == eStateStopped;
- }
-
- bool GetExitStatus(int* status)
- {
- if (GetState() == eStateExited)
- {
- if (status)
- *status = m_exit_status;
- return true;
- }
- return false;
- }
- void SetExitStatus(int status)
- {
- m_exit_status = status;
- SetState(eStateExited);
- }
- const char * GetExitInfo ()
- {
- return m_exit_info.c_str();
- }
-
- void SetExitInfo (const char *info);
-
- uint32_t StopCount() const { return m_stop_count; }
- void SetChildFileDescriptors (int stdin_fileno, int stdout_fileno, int stderr_fileno)
- {
- m_child_stdin = stdin_fileno;
- m_child_stdout = stdout_fileno;
- m_child_stderr = stderr_fileno;
- }
-
- int GetStdinFileDescriptor () const { return m_child_stdin; }
- int GetStdoutFileDescriptor () const { return m_child_stdout; }
- int GetStderrFileDescriptor () const { return m_child_stderr; }
- void AppendSTDOUT (char* s, size_t len);
- size_t GetAvailableSTDOUT (char *buf, size_t buf_size);
- size_t GetAvailableSTDERR (char *buf, size_t buf_size);
- void CloseChildFileDescriptors ()
- {
- if (m_child_stdin >= 0)
- {
- ::close (m_child_stdin);
- m_child_stdin = -1;
- }
- if (m_child_stdout >= 0)
- {
- ::close (m_child_stdout);
- m_child_stdout = -1;
- }
- if (m_child_stderr >= 0)
- {
- ::close (m_child_stderr);
- m_child_stderr = -1;
- }
- }
+ pid_t SBLaunchForDebug(const char *app_bundle_path, char const *argv[],
+ char const *envp[], bool no_stdio, bool disable_aslr,
+ DNBError &launch_err);
+ static pid_t SBForkChildForPTraceDebugging(const char *path,
+ char const *argv[],
+ char const *envp[], bool no_stdio,
+ MachProcess *process,
+ DNBError &launch_err);
+#endif // WITH_SPRINGBOARD
+ nub_addr_t LookupSymbol(const char *name, const char *shlib);
+ void SetNameToAddressCallback(DNBCallbackNameToAddress callback,
+ void *baton) {
+ m_name_to_addr_callback = callback;
+ m_name_to_addr_baton = baton;
+ }
+ void
+ SetSharedLibraryInfoCallback(DNBCallbackCopyExecutableImageInfos callback,
+ void *baton) {
+ m_image_infos_callback = callback;
+ m_image_infos_baton = baton;
+ }
+
+ bool Resume(const DNBThreadResumeActions &thread_actions);
+ bool Signal(int signal, const struct timespec *timeout_abstime = NULL);
+ bool Interrupt();
+ bool SendEvent(const char *event, DNBError &send_err);
+ bool Kill(const struct timespec *timeout_abstime = NULL);
+ bool Detach();
+ nub_size_t ReadMemory(nub_addr_t addr, nub_size_t size, void *buf);
+ nub_size_t WriteMemory(nub_addr_t addr, nub_size_t size, const void *buf);
+
+ //----------------------------------------------------------------------
+ // Path and arg accessors
+ //----------------------------------------------------------------------
+ const char *Path() const { return m_path.c_str(); }
+ size_t ArgumentCount() const { return m_args.size(); }
+ const char *ArgumentAtIndex(size_t arg_idx) const {
+ if (arg_idx < m_args.size())
+ return m_args[arg_idx].c_str();
+ return NULL;
+ }
+
+ //----------------------------------------------------------------------
+ // Breakpoint functions
+ //----------------------------------------------------------------------
+ DNBBreakpoint *CreateBreakpoint(nub_addr_t addr, nub_size_t length,
+ bool hardware);
+ bool DisableBreakpoint(nub_addr_t addr, bool remove);
+ void DisableAllBreakpoints(bool remove);
+ bool EnableBreakpoint(nub_addr_t addr);
+ DNBBreakpointList &Breakpoints() { return m_breakpoints; }
+ const DNBBreakpointList &Breakpoints() const { return m_breakpoints; }
+
+ //----------------------------------------------------------------------
+ // Watchpoint functions
+ //----------------------------------------------------------------------
+ DNBBreakpoint *CreateWatchpoint(nub_addr_t addr, nub_size_t length,
+ uint32_t watch_type, bool hardware);
+ bool DisableWatchpoint(nub_addr_t addr, bool remove);
+ void DisableAllWatchpoints(bool remove);
+ bool EnableWatchpoint(nub_addr_t addr);
+ uint32_t GetNumSupportedHardwareWatchpoints() const;
+ DNBBreakpointList &Watchpoints() { return m_watchpoints; }
+ const DNBBreakpointList &Watchpoints() const { return m_watchpoints; }
+
+ //----------------------------------------------------------------------
+ // Exception thread functions
+ //----------------------------------------------------------------------
+ bool StartSTDIOThread();
+ static void *STDIOThread(void *arg);
+ void ExceptionMessageReceived(const MachException::Message &exceptionMessage);
+ task_t ExceptionMessageBundleComplete();
+ void SharedLibrariesUpdated();
+ nub_size_t CopyImageInfos(struct DNBExecutableImageInfo **image_infos,
+ bool only_changed);
+
+ //----------------------------------------------------------------------
+ // Profile functions
+ //----------------------------------------------------------------------
+ void SetEnableAsyncProfiling(bool enable, uint64_t internal_usec,
+ DNBProfileDataScanType scan_type);
+ bool IsProfilingEnabled() { return m_profile_enabled; }
+ useconds_t ProfileInterval() { return m_profile_interval_usec; }
+ bool StartProfileThread();
+ static void *ProfileThread(void *arg);
+ void SignalAsyncProfileData(const char *info);
+ size_t GetAsyncProfileData(char *buf, size_t buf_size);
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+ pid_t ProcessID() const { return m_pid; }
+ bool ProcessIDIsValid() const { return m_pid > 0; }
+ pid_t SetProcessID(pid_t pid);
+ MachTask &Task() { return m_task; }
+ const MachTask &Task() const { return m_task; }
+
+ PThreadEvent &Events() { return m_events; }
+ const DNBRegisterSetInfo *GetRegisterSetInfo(nub_thread_t tid,
+ nub_size_t *num_reg_sets) const;
+ bool GetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg,
+ DNBRegisterValue *reg_value) const;
+ bool SetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg,
+ const DNBRegisterValue *value) const;
+ nub_bool_t SyncThreadState(nub_thread_t tid);
+ const char *ThreadGetName(nub_thread_t tid);
+ nub_state_t ThreadGetState(nub_thread_t tid);
+ ThreadInfo::QoS GetRequestedQoS(nub_thread_t tid, nub_addr_t tsd,
+ uint64_t dti_qos_class_index);
+ nub_addr_t GetPThreadT(nub_thread_t tid);
+ nub_addr_t GetDispatchQueueT(nub_thread_t tid);
+ nub_addr_t
+ GetTSDAddressForThread(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);
+
+ bool GetMachOInformationFromMemory(nub_addr_t mach_o_header_addr,
+ int wordsize,
+ struct mach_o_information &inf);
+ JSONGenerator::ObjectSP FormatDynamicLibrariesIntoJSON(
+ const std::vector<struct binary_image_information> &image_infos);
+ void GetAllLoadedBinariesViaDYLDSPI(
+ std::vector<struct binary_image_information> &image_infos);
+ JSONGenerator::ObjectSP GetLoadedDynamicLibrariesInfos(
+ nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count);
+ JSONGenerator::ObjectSP
+ GetLibrariesInfoForAddresses(nub_process_t pid,
+ std::vector<uint64_t> &macho_addresses);
+ JSONGenerator::ObjectSP GetAllLoadedLibrariesInfos(nub_process_t pid);
+ JSONGenerator::ObjectSP GetSharedCacheInfo(nub_process_t pid);
+
+ nub_size_t GetNumThreads() const;
+ nub_thread_t GetThreadAtIndex(nub_size_t thread_idx) const;
+ nub_thread_t GetCurrentThread();
+ nub_thread_t GetCurrentThreadMachPort();
+ nub_thread_t SetCurrentThread(nub_thread_t tid);
+ MachThreadList &GetThreadList() { return m_thread_list; }
+ bool GetThreadStoppedReason(nub_thread_t tid,
+ struct DNBThreadStopInfo *stop_info);
+ void DumpThreadStoppedReason(nub_thread_t tid) const;
+ const char *GetThreadInfo(nub_thread_t tid) const;
+
+ nub_thread_t GetThreadIDForMachPortNumber(thread_t mach_port_number) const;
+
+ uint32_t GetCPUType();
+ nub_state_t GetState();
+ void SetState(nub_state_t state);
+ bool IsRunning(nub_state_t state) {
+ return state == eStateRunning || IsStepping(state);
+ }
+ bool IsStepping(nub_state_t state) { return state == eStateStepping; }
+ bool CanResume(nub_state_t state) { return state == eStateStopped; }
+
+ bool GetExitStatus(int *status) {
+ if (GetState() == eStateExited) {
+ if (status)
+ *status = m_exit_status;
+ return true;
+ }
+ return false;
+ }
+ void SetExitStatus(int status) {
+ m_exit_status = status;
+ SetState(eStateExited);
+ }
+ const char *GetExitInfo() { return m_exit_info.c_str(); }
+
+ void SetExitInfo(const char *info);
+
+ uint32_t StopCount() const { return m_stop_count; }
+ void SetChildFileDescriptors(int stdin_fileno, int stdout_fileno,
+ int stderr_fileno) {
+ m_child_stdin = stdin_fileno;
+ m_child_stdout = stdout_fileno;
+ m_child_stderr = stderr_fileno;
+ }
+
+ int GetStdinFileDescriptor() const { return m_child_stdin; }
+ int GetStdoutFileDescriptor() const { return m_child_stdout; }
+ int GetStderrFileDescriptor() const { return m_child_stderr; }
+ void AppendSTDOUT(char *s, size_t len);
+ size_t GetAvailableSTDOUT(char *buf, size_t buf_size);
+ size_t GetAvailableSTDERR(char *buf, size_t buf_size);
+ void CloseChildFileDescriptors() {
+ if (m_child_stdin >= 0) {
+ ::close(m_child_stdin);
+ m_child_stdin = -1;
+ }
+ if (m_child_stdout >= 0) {
+ ::close(m_child_stdout);
+ m_child_stdout = -1;
+ }
+ if (m_child_stderr >= 0) {
+ ::close(m_child_stderr);
+ m_child_stderr = -1;
+ }
+ }
+
+ bool ProcessUsingSpringBoard() const {
+ return (m_flags & eMachProcessFlagsUsingSBS) != 0;
+ }
+ bool ProcessUsingBackBoard() const {
+ return (m_flags & eMachProcessFlagsUsingBKS) != 0;
+ }
- bool ProcessUsingSpringBoard() const { return (m_flags & eMachProcessFlagsUsingSBS) != 0; }
- bool ProcessUsingBackBoard() const { return (m_flags & eMachProcessFlagsUsingBKS) != 0; }
+ Genealogy::ThreadActivitySP GetGenealogyInfoForThread(nub_thread_t tid,
+ bool &timed_out);
- Genealogy::ThreadActivitySP GetGenealogyInfoForThread (nub_thread_t tid, bool &timed_out);
+ Genealogy::ProcessExecutableInfoSP GetGenealogyImageInfo(size_t idx);
- Genealogy::ProcessExecutableInfoSP GetGenealogyImageInfo (size_t idx);
-
- DNBProfileDataScanType GetProfileScanType () { return m_profile_scan_type; }
+ DNBProfileDataScanType GetProfileScanType() { return m_profile_scan_type; }
private:
- enum
- {
- eMachProcessFlagsNone = 0,
- eMachProcessFlagsAttached = (1 << 0),
- eMachProcessFlagsUsingSBS = (1 << 1),
- eMachProcessFlagsUsingBKS = (1 << 2),
- eMachProcessFlagsUsingFBS = (1 << 3)
- };
- void Clear (bool detaching = false);
- void ReplyToAllExceptions ();
- void PrivateResume ();
-
- uint32_t Flags () const { return m_flags; }
- nub_state_t DoSIGSTOP (bool clear_bps_and_wps, bool allow_running, uint32_t *thread_idx_ptr);
-
- pid_t m_pid; // Process ID of child process
- cpu_type_t m_cpu_type; // The CPU type of this process
- int m_child_stdin;
- int m_child_stdout;
- int m_child_stderr;
- std::string m_path; // A path to the executable if we have one
- std::vector<std::string> m_args; // The arguments with which the process was lauched
- int m_exit_status; // The exit status for the process
- std::string m_exit_info; // Any extra info that we may have about the exit
- MachTask m_task; // The mach task for this process
- uint32_t m_flags; // Process specific flags (see eMachProcessFlags enums)
- uint32_t m_stop_count; // A count of many times have we stopped
- pthread_t m_stdio_thread; // Thread ID for the thread that watches for child process stdio
- PThreadMutex m_stdio_mutex; // Multithreaded protection for stdio
- std::string m_stdout_data;
-
- bool m_profile_enabled; // A flag to indicate if profiling is enabled
- useconds_t m_profile_interval_usec; // If enable, the profiling interval in microseconds
- DNBProfileDataScanType m_profile_scan_type; // Indicates what needs to be profiled
- pthread_t m_profile_thread; // Thread ID for the thread that profiles the inferior
- PThreadMutex m_profile_data_mutex; // Multithreaded protection for profile info data
- std::vector<std::string> m_profile_data; // Profile data, must be protected by m_profile_data_mutex
-
- DNBThreadResumeActions m_thread_actions; // The thread actions for the current MachProcess::Resume() call
- MachException::Message::collection
- m_exception_messages; // A collection of exception messages caught when listening to the exception port
- PThreadMutex m_exception_messages_mutex; // Multithreaded protection for m_exception_messages
-
- MachThreadList m_thread_list; // A list of threads that is maintained/updated after each stop
- Genealogy m_activities; // A list of activities that is updated after every stop lazily
- nub_state_t m_state; // The state of our process
- PThreadMutex m_state_mutex; // Multithreaded protection for m_state
- PThreadEvent m_events; // Process related events in the child processes lifetime can be waited upon
- PThreadEvent m_private_events; // Used to coordinate running and stopping the process without affecting m_events
- DNBBreakpointList m_breakpoints; // Breakpoint list for this process
- DNBBreakpointList m_watchpoints; // Watchpoint list for this process
- DNBCallbackNameToAddress m_name_to_addr_callback;
- void * m_name_to_addr_baton;
- DNBCallbackCopyExecutableImageInfos
- m_image_infos_callback;
- void * m_image_infos_baton;
- std::string m_bundle_id; // If we are a SB or BKS process, this will be our bundle ID.
- int m_sent_interrupt_signo; // When we call MachProcess::Interrupt(), we want to send a single signal
- // to the inferior and only send the signal if we aren't already stopped.
- // If we end up sending a signal to stop the process we store it until we
- // receive an exception with this signal. This helps us to verify we got
- // the signal that interrupted the process. We might stop due to another
- // reason after an interrupt signal is sent, so this helps us ensure that
- // we don't report a spurious stop on the next resume.
- int m_auto_resume_signo; // If we resume the process and still haven't received our interrupt signal
- // acknownledgement, we will shortly after the next resume. We store the
- // interrupt signal in this variable so when we get the interrupt signal
- // as the sole reason for the process being stopped, we can auto resume
- // the process.
- bool m_did_exec;
-
- void * (*m_dyld_process_info_create) (task_t task, uint64_t timestamp, kern_return_t* kernelError);
- void (*m_dyld_process_info_for_each_image) (void* info, void (^callback)(uint64_t machHeaderAddress, const uuid_t uuid, const char* path));
- void (*m_dyld_process_info_release) (void* info);
- void (*m_dyld_process_info_get_cache) (void* info, void* cacheInfo);
+ enum {
+ eMachProcessFlagsNone = 0,
+ eMachProcessFlagsAttached = (1 << 0),
+ eMachProcessFlagsUsingSBS = (1 << 1),
+ eMachProcessFlagsUsingBKS = (1 << 2),
+ eMachProcessFlagsUsingFBS = (1 << 3)
+ };
+ void Clear(bool detaching = false);
+ void ReplyToAllExceptions();
+ void PrivateResume();
+
+ uint32_t Flags() const { return m_flags; }
+ nub_state_t DoSIGSTOP(bool clear_bps_and_wps, bool allow_running,
+ uint32_t *thread_idx_ptr);
+
+ pid_t m_pid; // Process ID of child process
+ cpu_type_t m_cpu_type; // The CPU type of this process
+ int m_child_stdin;
+ int m_child_stdout;
+ int m_child_stderr;
+ std::string m_path; // A path to the executable if we have one
+ std::vector<std::string>
+ m_args; // The arguments with which the process was lauched
+ int m_exit_status; // The exit status for the process
+ std::string m_exit_info; // Any extra info that we may have about the exit
+ MachTask m_task; // The mach task for this process
+ uint32_t m_flags; // Process specific flags (see eMachProcessFlags enums)
+ uint32_t m_stop_count; // A count of many times have we stopped
+ pthread_t m_stdio_thread; // Thread ID for the thread that watches for child
+ // process stdio
+ PThreadMutex m_stdio_mutex; // Multithreaded protection for stdio
+ std::string m_stdout_data;
+
+ bool m_profile_enabled; // A flag to indicate if profiling is enabled
+ useconds_t m_profile_interval_usec; // If enable, the profiling interval in
+ // microseconds
+ DNBProfileDataScanType
+ m_profile_scan_type; // Indicates what needs to be profiled
+ pthread_t
+ m_profile_thread; // Thread ID for the thread that profiles the inferior
+ PThreadMutex
+ m_profile_data_mutex; // Multithreaded protection for profile info data
+ std::vector<std::string>
+ m_profile_data; // Profile data, must be protected by m_profile_data_mutex
+
+ DNBThreadResumeActions m_thread_actions; // The thread actions for the current
+ // MachProcess::Resume() call
+ MachException::Message::collection m_exception_messages; // A collection of
+ // exception messages
+ // caught when
+ // listening to the
+ // exception port
+ PThreadMutex m_exception_messages_mutex; // Multithreaded protection for
+ // m_exception_messages
+
+ MachThreadList m_thread_list; // A list of threads that is maintained/updated
+ // after each stop
+ Genealogy m_activities; // A list of activities that is updated after every
+ // stop lazily
+ nub_state_t m_state; // The state of our process
+ PThreadMutex m_state_mutex; // Multithreaded protection for m_state
+ PThreadEvent m_events; // Process related events in the child processes
+ // lifetime can be waited upon
+ PThreadEvent m_private_events; // Used to coordinate running and stopping the
+ // process without affecting m_events
+ DNBBreakpointList m_breakpoints; // Breakpoint list for this process
+ DNBBreakpointList m_watchpoints; // Watchpoint list for this process
+ DNBCallbackNameToAddress m_name_to_addr_callback;
+ void *m_name_to_addr_baton;
+ DNBCallbackCopyExecutableImageInfos m_image_infos_callback;
+ void *m_image_infos_baton;
+ std::string
+ m_bundle_id; // If we are a SB or BKS process, this will be our bundle ID.
+ int m_sent_interrupt_signo; // When we call MachProcess::Interrupt(), we want
+ // to send a single signal
+ // to the inferior and only send the signal if we aren't already stopped.
+ // If we end up sending a signal to stop the process we store it until we
+ // receive an exception with this signal. This helps us to verify we got
+ // the signal that interrupted the process. We might stop due to another
+ // reason after an interrupt signal is sent, so this helps us ensure that
+ // we don't report a spurious stop on the next resume.
+ int m_auto_resume_signo; // If we resume the process and still haven't
+ // received our interrupt signal
+ // acknownledgement, we will shortly after the next resume. We store the
+ // interrupt signal in this variable so when we get the interrupt signal
+ // as the sole reason for the process being stopped, we can auto resume
+ // the process.
+ bool m_did_exec;
+
+ void *(*m_dyld_process_info_create)(task_t task, uint64_t timestamp,
+ kern_return_t *kernelError);
+ void (*m_dyld_process_info_for_each_image)(
+ void *info, void (^callback)(uint64_t machHeaderAddress,
+ const uuid_t uuid, const char *path));
+ void (*m_dyld_process_info_release)(void *info);
+ void (*m_dyld_process_info_get_cache)(void *info, void *cacheInfo);
};
-
#endif // __MachProcess_h__
Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.mm
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.mm?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.mm (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.mm Tue Sep 6 15:57:50 2016
@@ -12,23 +12,23 @@
//===----------------------------------------------------------------------===//
#include "DNB.h"
+#include "MacOSX/CFUtils.h"
+#include "SysSignal.h"
#include <dlfcn.h>
#include <inttypes.h>
+#include <mach-o/loader.h>
#include <mach/mach.h>
#include <mach/task.h>
+#include <pthread.h>
#include <signal.h>
#include <spawn.h>
#include <sys/fcntl.h>
-#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
+#include <sys/types.h>
#include <unistd.h>
-#include <pthread.h>
-#include <mach-o/loader.h>
#include <uuid/uuid.h>
-#include "MacOSX/CFUtils.h"
-#include "SysSignal.h"
#include <algorithm>
#include <map>
@@ -48,329 +48,359 @@
#ifdef WITH_SPRINGBOARD
#include <CoreFoundation/CoreFoundation.h>
-#include <SpringBoardServices/SpringBoardServer.h>
#include <SpringBoardServices/SBSWatchdogAssertion.h>
+#include <SpringBoardServices/SpringBoardServer.h>
-static bool
-IsSBProcess (nub_process_t pid)
-{
- CFReleaser<CFArrayRef> appIdsForPID (::SBSCopyDisplayIdentifiersForProcessID(pid));
- return appIdsForPID.get() != NULL;
+static bool IsSBProcess(nub_process_t pid) {
+ CFReleaser<CFArrayRef> appIdsForPID(
+ ::SBSCopyDisplayIdentifiersForProcessID(pid));
+ return appIdsForPID.get() != NULL;
}
#endif // WITH_SPRINGBOARD
-#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS)
+#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) || defined(WITH_FBS)
// This returns a CFRetained pointer to the Bundle ID for app_bundle_path,
// or NULL if there was some problem getting the bundle id.
-static CFStringRef CopyBundleIDForPath (const char *app_bundle_path, DNBError &err_str);
+static CFStringRef CopyBundleIDForPath(const char *app_bundle_path,
+ DNBError &err_str);
#endif
#if defined(WITH_BKS) || defined(WITH_FBS)
#import <Foundation/Foundation.h>
static const int OPEN_APPLICATION_TIMEOUT_ERROR = 111;
-typedef void (*SetErrorFunction) (NSInteger, DNBError &);
-typedef bool (*CallOpenApplicationFunction) (NSString *bundleIDNSStr, NSDictionary *options, DNBError &error, pid_t *return_pid);
-// This function runs the BKSSystemService (or FBSSystemService) method openApplication:options:clientPort:withResult,
+typedef void (*SetErrorFunction)(NSInteger, DNBError &);
+typedef bool (*CallOpenApplicationFunction)(NSString *bundleIDNSStr,
+ NSDictionary *options,
+ DNBError &error, pid_t *return_pid);
+// This function runs the BKSSystemService (or FBSSystemService) method
+// openApplication:options:clientPort:withResult,
// messaging the app passed in bundleIDNSStr.
// The function should be run inside of an NSAutoReleasePool.
//
-// It will use the "options" dictionary passed in, and fill the error passed in if there is an error.
-// If return_pid is not NULL, we'll fetch the pid that was made for the bundleID.
+// It will use the "options" dictionary passed in, and fill the error passed in
+// if there is an error.
+// If return_pid is not NULL, we'll fetch the pid that was made for the
+// bundleID.
// If bundleIDNSStr is NULL, then the system application will be messaged.
-template <typename OpenFlavor, typename ErrorFlavor, ErrorFlavor no_error_enum_value, SetErrorFunction error_function>
-static bool
-CallBoardSystemServiceOpenApplication (NSString *bundleIDNSStr, NSDictionary *options, DNBError &error, pid_t *return_pid)
-{
- // Now make our systemService:
- OpenFlavor *system_service = [[OpenFlavor alloc] init];
-
- if (bundleIDNSStr == nil)
- {
- bundleIDNSStr = [system_service systemApplicationBundleIdentifier];
- if (bundleIDNSStr == nil)
- {
- // Okay, no system app...
- error.SetErrorString("No system application to message.");
- return false;
- }
- }
-
- mach_port_t client_port = [system_service createClientPort];
- __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- __block ErrorFlavor open_app_error = no_error_enum_value;
- bool wants_pid = (return_pid != NULL);
- __block pid_t pid_in_block;
-
- const char *cstr = [bundleIDNSStr UTF8String];
- if (!cstr)
- cstr = "<Unknown Bundle ID>";
-
- DNBLog ("About to launch process for bundle ID: %s", cstr);
- [system_service openApplication: bundleIDNSStr
- options: options
- clientPort: client_port
- withResult: ^(NSError *bks_error)
- {
- // The system service will cleanup the client port we created for us.
- if (bks_error)
- open_app_error = (ErrorFlavor)[bks_error code];
-
- if (open_app_error == no_error_enum_value)
- {
- if (wants_pid)
- {
- pid_in_block = [system_service pidForApplication: bundleIDNSStr];
- DNBLog("In completion handler, got pid for bundle id, pid: %d.", pid_in_block);
- DNBLogThreadedIf(LOG_PROCESS, "In completion handler, got pid for bundle id, pid: %d.", pid_in_block);
- }
- else
- DNBLogThreadedIf (LOG_PROCESS, "In completion handler: success.");
- }
- else
- {
- const char *error_str = [(NSString *)[bks_error localizedDescription] UTF8String];
- DNBLogThreadedIf(LOG_PROCESS, "In completion handler for send event, got error \"%s\"(%ld).",
- error_str ? error_str : "<unknown error>",
- open_app_error);
- // REMOVE ME
- DNBLogError ("In completion handler for send event, got error \"%s\"(%ld).",
- error_str ? error_str : "<unknown error>",
- open_app_error);
- }
-
- [system_service release];
- dispatch_semaphore_signal(semaphore);
- }
-
- ];
-
- const uint32_t timeout_secs = 9;
-
- dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC);
-
- long success = dispatch_semaphore_wait(semaphore, timeout) == 0;
-
- dispatch_release(semaphore);
-
- if (!success)
-{
- DNBLogError("timed out trying to send openApplication to %s.", cstr);
- error.SetError (OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
- error.SetErrorString ("timed out trying to launch app");
- }
- else if (open_app_error != no_error_enum_value)
- {
- error_function (open_app_error, error);
- DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %u", cstr, open_app_error);
- success = false;
- }
- else if (wants_pid)
- {
- *return_pid = pid_in_block;
- DNBLogThreadedIf (LOG_PROCESS, "Out of completion handler, pid from block %d and passing out: %d", pid_in_block, *return_pid);
-}
-
+template <typename OpenFlavor, typename ErrorFlavor,
+ ErrorFlavor no_error_enum_value, SetErrorFunction error_function>
+static bool CallBoardSystemServiceOpenApplication(NSString *bundleIDNSStr,
+ NSDictionary *options,
+ DNBError &error,
+ pid_t *return_pid) {
+ // Now make our systemService:
+ OpenFlavor *system_service = [[OpenFlavor alloc] init];
+
+ if (bundleIDNSStr == nil) {
+ bundleIDNSStr = [system_service systemApplicationBundleIdentifier];
+ if (bundleIDNSStr == nil) {
+ // Okay, no system app...
+ error.SetErrorString("No system application to message.");
+ return false;
+ }
+ }
+
+ mach_port_t client_port = [system_service createClientPort];
+ __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
+ __block ErrorFlavor open_app_error = no_error_enum_value;
+ bool wants_pid = (return_pid != NULL);
+ __block pid_t pid_in_block;
+
+ const char *cstr = [bundleIDNSStr UTF8String];
+ if (!cstr)
+ cstr = "<Unknown Bundle ID>";
+
+ DNBLog("About to launch process for bundle ID: %s", cstr);
+ [system_service
+ openApplication:bundleIDNSStr
+ options:options
+ clientPort:client_port
+ withResult:^(NSError *bks_error) {
+ // The system service will cleanup the client port we created for
+ // us.
+ if (bks_error)
+ open_app_error = (ErrorFlavor)[bks_error code];
+
+ if (open_app_error == no_error_enum_value) {
+ if (wants_pid) {
+ pid_in_block =
+ [system_service pidForApplication:bundleIDNSStr];
+ DNBLog(
+ "In completion handler, got pid for bundle id, pid: %d.",
+ pid_in_block);
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "In completion handler, got pid for bundle id, pid: %d.",
+ pid_in_block);
+ } else
+ DNBLogThreadedIf(LOG_PROCESS,
+ "In completion handler: success.");
+ } else {
+ const char *error_str =
+ [(NSString *)[bks_error localizedDescription] UTF8String];
+ DNBLogThreadedIf(LOG_PROCESS, "In completion handler for send "
+ "event, got error \"%s\"(%ld).",
+ error_str ? error_str : "<unknown error>",
+ open_app_error);
+ // REMOVE ME
+ DNBLogError("In completion handler for send event, got error "
+ "\"%s\"(%ld).",
+ error_str ? error_str : "<unknown error>",
+ open_app_error);
+ }
+
+ [system_service release];
+ dispatch_semaphore_signal(semaphore);
+ }
+
+ ];
+
+ const uint32_t timeout_secs = 9;
+
+ dispatch_time_t timeout =
+ dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC);
+
+ long success = dispatch_semaphore_wait(semaphore, timeout) == 0;
+
+ dispatch_release(semaphore);
+
+ if (!success) {
+ DNBLogError("timed out trying to send openApplication to %s.", cstr);
+ error.SetError(OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
+ error.SetErrorString("timed out trying to launch app");
+ } else if (open_app_error != no_error_enum_value) {
+ error_function(open_app_error, error);
+ DNBLogError("unable to launch the application with CFBundleIdentifier '%s' "
+ "bks_error = %u",
+ cstr, open_app_error);
+ success = false;
+ } else if (wants_pid) {
+ *return_pid = pid_in_block;
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "Out of completion handler, pid from block %d and passing out: %d",
+ pid_in_block, *return_pid);
+ }
- return success;
+ return success;
}
#endif
#ifdef WITH_BKS
#import <Foundation/Foundation.h>
-extern "C"
-{
-#import <BackBoardServices/BackBoardServices.h>
-#import <BackBoardServices/BKSSystemService_LaunchServices.h>
+extern "C" {
#import <BackBoardServices/BKSOpenApplicationConstants_Private.h>
+#import <BackBoardServices/BKSSystemService_LaunchServices.h>
+#import <BackBoardServices/BackBoardServices.h>
}
-static bool
-IsBKSProcess (nub_process_t pid)
-{
- BKSApplicationStateMonitor *state_monitor = [[BKSApplicationStateMonitor alloc] init];
- BKSApplicationState app_state = [state_monitor mostElevatedApplicationStateForPID: pid];
- return app_state != BKSApplicationStateUnknown;
-}
-
-static void
-SetBKSError (NSInteger error_code, DNBError &error)
-{
- error.SetError (error_code, DNBError::BackBoard);
- NSString *err_nsstr = ::BKSOpenApplicationErrorCodeToString((BKSOpenApplicationErrorCode) error_code);
- const char *err_str = NULL;
- if (err_nsstr == NULL)
- err_str = "unknown BKS error";
- else
- {
- err_str = [err_nsstr UTF8String];
- if (err_str == NULL)
- err_str = "unknown BKS error";
- }
- error.SetErrorString(err_str);
-}
-
-static bool
-BKSAddEventDataToOptions (NSMutableDictionary *options, const char *event_data, DNBError &option_error)
-{
- if (strcmp (event_data, "BackgroundContentFetching") == 0)
- {
- DNBLog("Setting ActivateForEvent key in options dictionary.");
- NSDictionary *event_details = [NSDictionary dictionary];
- NSDictionary *event_dictionary = [NSDictionary dictionaryWithObject:event_details forKey:BKSActivateForEventOptionTypeBackgroundContentFetching];
- [options setObject: event_dictionary forKey: BKSOpenApplicationOptionKeyActivateForEvent];
- return true;
- }
- else
- {
- DNBLogError ("Unrecognized event type: %s. Ignoring.", event_data);
- option_error.SetErrorString("Unrecognized event data.");
- return false;
- }
-
-}
-
-static NSMutableDictionary *
-BKSCreateOptionsDictionary(const char *app_bundle_path, NSMutableArray *launch_argv, NSMutableDictionary *launch_envp, NSString *stdio_path, bool disable_aslr, const char *event_data)
-{
- NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
- if (launch_argv != nil)
- [debug_options setObject: launch_argv forKey: BKSDebugOptionKeyArguments];
- if (launch_envp != nil)
- [debug_options setObject: launch_envp forKey: BKSDebugOptionKeyEnvironment];
-
- [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardOutPath];
- [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardErrorPath];
- [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyWaitForDebugger];
- if (disable_aslr)
- [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyDisableASLR];
-
- // That will go in the overall dictionary:
-
- NSMutableDictionary *options = [NSMutableDictionary dictionary];
- [options setObject: debug_options forKey: BKSOpenApplicationOptionKeyDebuggingOptions];
- // And there are some other options at the top level in this dictionary:
- [options setObject: [NSNumber numberWithBool: YES] forKey: BKSOpenApplicationOptionKeyUnlockDevice];
-
- DNBError error;
- BKSAddEventDataToOptions (options, event_data, error);
-
- return options;
+static bool IsBKSProcess(nub_process_t pid) {
+ BKSApplicationStateMonitor *state_monitor =
+ [[BKSApplicationStateMonitor alloc] init];
+ BKSApplicationState app_state =
+ [state_monitor mostElevatedApplicationStateForPID:pid];
+ return app_state != BKSApplicationStateUnknown;
+}
+
+static void SetBKSError(NSInteger error_code, DNBError &error) {
+ error.SetError(error_code, DNBError::BackBoard);
+ NSString *err_nsstr = ::BKSOpenApplicationErrorCodeToString(
+ (BKSOpenApplicationErrorCode)error_code);
+ const char *err_str = NULL;
+ if (err_nsstr == NULL)
+ err_str = "unknown BKS error";
+ else {
+ err_str = [err_nsstr UTF8String];
+ if (err_str == NULL)
+ err_str = "unknown BKS error";
+ }
+ error.SetErrorString(err_str);
+}
+
+static bool BKSAddEventDataToOptions(NSMutableDictionary *options,
+ const char *event_data,
+ DNBError &option_error) {
+ if (strcmp(event_data, "BackgroundContentFetching") == 0) {
+ DNBLog("Setting ActivateForEvent key in options dictionary.");
+ NSDictionary *event_details = [NSDictionary dictionary];
+ NSDictionary *event_dictionary = [NSDictionary
+ dictionaryWithObject:event_details
+ forKey:
+ BKSActivateForEventOptionTypeBackgroundContentFetching];
+ [options setObject:event_dictionary
+ forKey:BKSOpenApplicationOptionKeyActivateForEvent];
+ return true;
+ } else {
+ DNBLogError("Unrecognized event type: %s. Ignoring.", event_data);
+ option_error.SetErrorString("Unrecognized event data.");
+ return false;
+ }
}
-static CallOpenApplicationFunction BKSCallOpenApplicationFunction = CallBoardSystemServiceOpenApplication<BKSSystemService, BKSOpenApplicationErrorCode, BKSOpenApplicationErrorCodeNone, SetBKSError>;
+static NSMutableDictionary *BKSCreateOptionsDictionary(
+ const char *app_bundle_path, NSMutableArray *launch_argv,
+ NSMutableDictionary *launch_envp, NSString *stdio_path, bool disable_aslr,
+ const char *event_data) {
+ NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+ if (launch_argv != nil)
+ [debug_options setObject:launch_argv forKey:BKSDebugOptionKeyArguments];
+ if (launch_envp != nil)
+ [debug_options setObject:launch_envp forKey:BKSDebugOptionKeyEnvironment];
+
+ [debug_options setObject:stdio_path forKey:BKSDebugOptionKeyStandardOutPath];
+ [debug_options setObject:stdio_path
+ forKey:BKSDebugOptionKeyStandardErrorPath];
+ [debug_options setObject:[NSNumber numberWithBool:YES]
+ forKey:BKSDebugOptionKeyWaitForDebugger];
+ if (disable_aslr)
+ [debug_options setObject:[NSNumber numberWithBool:YES]
+ forKey:BKSDebugOptionKeyDisableASLR];
+
+ // That will go in the overall dictionary:
+
+ NSMutableDictionary *options = [NSMutableDictionary dictionary];
+ [options setObject:debug_options
+ forKey:BKSOpenApplicationOptionKeyDebuggingOptions];
+ // And there are some other options at the top level in this dictionary:
+ [options setObject:[NSNumber numberWithBool:YES]
+ forKey:BKSOpenApplicationOptionKeyUnlockDevice];
+
+ DNBError error;
+ BKSAddEventDataToOptions(options, event_data, error);
+
+ return options;
+}
+
+static CallOpenApplicationFunction BKSCallOpenApplicationFunction =
+ CallBoardSystemServiceOpenApplication<
+ BKSSystemService, BKSOpenApplicationErrorCode,
+ BKSOpenApplicationErrorCodeNone, SetBKSError>;
#endif // WITH_BKS
#ifdef WITH_FBS
#import <Foundation/Foundation.h>
-extern "C"
-{
-#import <FrontBoardServices/FrontBoardServices.h>
-#import <FrontBoardServices/FBSSystemService_LaunchServices.h>
+extern "C" {
#import <FrontBoardServices/FBSOpenApplicationConstants_Private.h>
-#import <MobileCoreServices/MobileCoreServices.h>
+#import <FrontBoardServices/FBSSystemService_LaunchServices.h>
+#import <FrontBoardServices/FrontBoardServices.h>
#import <MobileCoreServices/LSResourceProxy.h>
+#import <MobileCoreServices/MobileCoreServices.h>
}
#ifdef WITH_BKS
-static bool
-IsFBSProcess (nub_process_t pid)
-{
- BKSApplicationStateMonitor *state_monitor = [[BKSApplicationStateMonitor alloc] init];
- BKSApplicationState app_state = [state_monitor mostElevatedApplicationStateForPID: pid];
- return app_state != BKSApplicationStateUnknown;
+static bool IsFBSProcess(nub_process_t pid) {
+ BKSApplicationStateMonitor *state_monitor =
+ [[BKSApplicationStateMonitor alloc] init];
+ BKSApplicationState app_state =
+ [state_monitor mostElevatedApplicationStateForPID:pid];
+ return app_state != BKSApplicationStateUnknown;
}
#else
-static bool
-IsFBSProcess (nub_process_t pid)
-{
- // FIXME: What is the FBS equivalent of BKSApplicationStateMonitor
- return true;
+static bool IsFBSProcess(nub_process_t pid) {
+ // FIXME: What is the FBS equivalent of BKSApplicationStateMonitor
+ return true;
}
#endif
-static void
-SetFBSError (NSInteger error_code, DNBError &error)
-{
- error.SetError ((DNBError::ValueType) error_code, DNBError::FrontBoard);
- NSString *err_nsstr = ::FBSOpenApplicationErrorCodeToString((FBSOpenApplicationErrorCode) error_code);
- const char *err_str = NULL;
- if (err_nsstr == NULL)
- err_str = "unknown FBS error";
- else
- {
- err_str = [err_nsstr UTF8String];
- if (err_str == NULL)
- err_str = "unknown FBS error";
- }
- error.SetErrorString(err_str);
-}
-
-static bool
-FBSAddEventDataToOptions (NSMutableDictionary *options, const char *event_data, DNBError &option_error)
-{
- if (strcmp (event_data, "BackgroundContentFetching") == 0)
- {
- DNBLog("Setting ActivateForEvent key in options dictionary.");
- NSDictionary *event_details = [NSDictionary dictionary];
- NSDictionary *event_dictionary = [NSDictionary dictionaryWithObject:event_details forKey:FBSActivateForEventOptionTypeBackgroundContentFetching];
- [options setObject: event_dictionary forKey: FBSOpenApplicationOptionKeyActivateForEvent];
- return true;
- }
- else
- {
- DNBLogError ("Unrecognized event type: %s. Ignoring.", event_data);
- option_error.SetErrorString("Unrecognized event data.");
- return false;
- }
-
+static void SetFBSError(NSInteger error_code, DNBError &error) {
+ error.SetError((DNBError::ValueType)error_code, DNBError::FrontBoard);
+ NSString *err_nsstr = ::FBSOpenApplicationErrorCodeToString(
+ (FBSOpenApplicationErrorCode)error_code);
+ const char *err_str = NULL;
+ if (err_nsstr == NULL)
+ err_str = "unknown FBS error";
+ else {
+ err_str = [err_nsstr UTF8String];
+ if (err_str == NULL)
+ err_str = "unknown FBS error";
+ }
+ error.SetErrorString(err_str);
+}
+
+static bool FBSAddEventDataToOptions(NSMutableDictionary *options,
+ const char *event_data,
+ DNBError &option_error) {
+ if (strcmp(event_data, "BackgroundContentFetching") == 0) {
+ DNBLog("Setting ActivateForEvent key in options dictionary.");
+ NSDictionary *event_details = [NSDictionary dictionary];
+ NSDictionary *event_dictionary = [NSDictionary
+ dictionaryWithObject:event_details
+ forKey:
+ FBSActivateForEventOptionTypeBackgroundContentFetching];
+ [options setObject:event_dictionary
+ forKey:FBSOpenApplicationOptionKeyActivateForEvent];
+ return true;
+ } else {
+ DNBLogError("Unrecognized event type: %s. Ignoring.", event_data);
+ option_error.SetErrorString("Unrecognized event data.");
+ return false;
+ }
}
static NSMutableDictionary *
-FBSCreateOptionsDictionary(const char *app_bundle_path, NSMutableArray *launch_argv, NSDictionary *launch_envp, NSString *stdio_path, bool disable_aslr, const char *event_data)
-{
- NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
-
- if (launch_argv != nil)
- [debug_options setObject: launch_argv forKey: FBSDebugOptionKeyArguments];
- if (launch_envp != nil)
- [debug_options setObject: launch_envp forKey: FBSDebugOptionKeyEnvironment];
-
- [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardOutPath];
- [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardErrorPath];
- [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyWaitForDebugger];
- if (disable_aslr)
- [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyDisableASLR];
-
- // That will go in the overall dictionary:
-
- NSMutableDictionary *options = [NSMutableDictionary dictionary];
- [options setObject: debug_options forKey: FBSOpenApplicationOptionKeyDebuggingOptions];
- // And there are some other options at the top level in this dictionary:
- [options setObject: [NSNumber numberWithBool: YES] forKey: FBSOpenApplicationOptionKeyUnlockDevice];
-
- // We have to get the "sequence ID & UUID" for this app bundle path and send them to FBS:
-
- NSURL *app_bundle_url = [NSURL fileURLWithPath: [NSString stringWithUTF8String: app_bundle_path] isDirectory: YES];
- LSApplicationProxy *app_proxy = [LSApplicationProxy applicationProxyForBundleURL: app_bundle_url];
- if (app_proxy)
- {
- DNBLog("Sending AppProxy info: sequence no: %lu, GUID: %s.", app_proxy.sequenceNumber, [app_proxy.cacheGUID.UUIDString UTF8String]);
- [options setObject: [NSNumber numberWithUnsignedInteger: app_proxy.sequenceNumber] forKey: FBSOpenApplicationOptionKeyLSSequenceNumber];
- [options setObject: app_proxy.cacheGUID.UUIDString forKey: FBSOpenApplicationOptionKeyLSCacheGUID];
- }
-
- DNBError error;
- FBSAddEventDataToOptions (options, event_data, error);
-
- return options;
-}
-static CallOpenApplicationFunction FBSCallOpenApplicationFunction = CallBoardSystemServiceOpenApplication<FBSSystemService, FBSOpenApplicationErrorCode, FBSOpenApplicationErrorCodeNone, SetFBSError>;
+FBSCreateOptionsDictionary(const char *app_bundle_path,
+ NSMutableArray *launch_argv,
+ NSDictionary *launch_envp, NSString *stdio_path,
+ bool disable_aslr, const char *event_data) {
+ NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+
+ if (launch_argv != nil)
+ [debug_options setObject:launch_argv forKey:FBSDebugOptionKeyArguments];
+ if (launch_envp != nil)
+ [debug_options setObject:launch_envp forKey:FBSDebugOptionKeyEnvironment];
+
+ [debug_options setObject:stdio_path forKey:FBSDebugOptionKeyStandardOutPath];
+ [debug_options setObject:stdio_path
+ forKey:FBSDebugOptionKeyStandardErrorPath];
+ [debug_options setObject:[NSNumber numberWithBool:YES]
+ forKey:FBSDebugOptionKeyWaitForDebugger];
+ if (disable_aslr)
+ [debug_options setObject:[NSNumber numberWithBool:YES]
+ forKey:FBSDebugOptionKeyDisableASLR];
+
+ // That will go in the overall dictionary:
+
+ NSMutableDictionary *options = [NSMutableDictionary dictionary];
+ [options setObject:debug_options
+ forKey:FBSOpenApplicationOptionKeyDebuggingOptions];
+ // And there are some other options at the top level in this dictionary:
+ [options setObject:[NSNumber numberWithBool:YES]
+ forKey:FBSOpenApplicationOptionKeyUnlockDevice];
+
+ // We have to get the "sequence ID & UUID" for this app bundle path and send
+ // them to FBS:
+
+ NSURL *app_bundle_url =
+ [NSURL fileURLWithPath:[NSString stringWithUTF8String:app_bundle_path]
+ isDirectory:YES];
+ LSApplicationProxy *app_proxy =
+ [LSApplicationProxy applicationProxyForBundleURL:app_bundle_url];
+ if (app_proxy) {
+ DNBLog("Sending AppProxy info: sequence no: %lu, GUID: %s.",
+ app_proxy.sequenceNumber,
+ [app_proxy.cacheGUID.UUIDString UTF8String]);
+ [options
+ setObject:[NSNumber numberWithUnsignedInteger:app_proxy.sequenceNumber]
+ forKey:FBSOpenApplicationOptionKeyLSSequenceNumber];
+ [options setObject:app_proxy.cacheGUID.UUIDString
+ forKey:FBSOpenApplicationOptionKeyLSCacheGUID];
+ }
+
+ DNBError error;
+ FBSAddEventDataToOptions(options, event_data, error);
+
+ return options;
+}
+static CallOpenApplicationFunction FBSCallOpenApplicationFunction =
+ CallBoardSystemServiceOpenApplication<
+ FBSSystemService, FBSOpenApplicationErrorCode,
+ FBSOpenApplicationErrorCodeNone, SetFBSError>;
#endif // WITH_FBS
#if 0
-#define DEBUG_LOG(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#define DEBUG_LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define DEBUG_LOG(fmt, ...)
#endif
@@ -380,1055 +410,1015 @@ static CallOpenApplicationFunction FBSCa
#endif
#ifndef _POSIX_SPAWN_DISABLE_ASLR
-#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
+#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
#endif
-MachProcess::MachProcess() :
- m_pid (0),
- m_cpu_type (0),
- m_child_stdin (-1),
- m_child_stdout (-1),
- m_child_stderr (-1),
- m_path (),
- m_args (),
- m_task (this),
- m_flags (eMachProcessFlagsNone),
- m_stdio_thread (0),
- m_stdio_mutex (PTHREAD_MUTEX_RECURSIVE),
- m_stdout_data (),
- m_profile_enabled (false),
- m_profile_interval_usec (0),
- m_profile_thread (0),
- m_profile_data_mutex(PTHREAD_MUTEX_RECURSIVE),
- m_profile_data (),
- m_thread_actions (),
- m_exception_messages (),
- m_exception_messages_mutex (PTHREAD_MUTEX_RECURSIVE),
- m_thread_list (),
- m_activities (),
- m_state (eStateUnloaded),
- m_state_mutex (PTHREAD_MUTEX_RECURSIVE),
- m_events (0, kAllEventsMask),
- m_private_events (0, kAllEventsMask),
- m_breakpoints (),
- m_watchpoints (),
- m_name_to_addr_callback(NULL),
- m_name_to_addr_baton(NULL),
- m_image_infos_callback(NULL),
- m_image_infos_baton(NULL),
- m_sent_interrupt_signo (0),
- m_auto_resume_signo (0),
- m_did_exec (false),
- m_dyld_process_info_create (nullptr),
- m_dyld_process_info_for_each_image (nullptr),
- m_dyld_process_info_release (nullptr),
- m_dyld_process_info_get_cache (nullptr)
-{
- m_dyld_process_info_create = (void * (*) (task_t task, uint64_t timestamp, kern_return_t* kernelError)) dlsym (RTLD_DEFAULT, "_dyld_process_info_create");
- m_dyld_process_info_for_each_image = (void (*)(void *info, void (^)(uint64_t machHeaderAddress, const uuid_t uuid, const char* path))) dlsym (RTLD_DEFAULT, "_dyld_process_info_for_each_image");
- m_dyld_process_info_release = (void (*) (void* info)) dlsym (RTLD_DEFAULT, "_dyld_process_info_release");
- m_dyld_process_info_get_cache = (void (*) (void* info, void* cacheInfo)) dlsym (RTLD_DEFAULT, "_dyld_process_info_get_cache");
-
- DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__);
-}
-
-MachProcess::~MachProcess()
-{
- DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__);
- Clear();
-}
-
-pid_t
-MachProcess::SetProcessID(pid_t pid)
-{
- // Free any previous process specific data or resources
- Clear();
- // Set the current PID appropriately
- if (pid == 0)
- m_pid = ::getpid ();
- else
- m_pid = pid;
- return m_pid; // Return actually PID in case a zero pid was passed in
-}
-
-nub_state_t
-MachProcess::GetState()
-{
- // If any other threads access this we will need a mutex for it
- PTHREAD_MUTEX_LOCKER(locker, m_state_mutex);
- return m_state;
-}
-
-const char *
-MachProcess::ThreadGetName(nub_thread_t tid)
-{
- return m_thread_list.GetName(tid);
+MachProcess::MachProcess()
+ : m_pid(0), m_cpu_type(0), m_child_stdin(-1), m_child_stdout(-1),
+ m_child_stderr(-1), m_path(), m_args(), m_task(this),
+ m_flags(eMachProcessFlagsNone), m_stdio_thread(0),
+ m_stdio_mutex(PTHREAD_MUTEX_RECURSIVE), m_stdout_data(),
+ m_profile_enabled(false), m_profile_interval_usec(0), m_profile_thread(0),
+ m_profile_data_mutex(PTHREAD_MUTEX_RECURSIVE), m_profile_data(),
+ m_thread_actions(), m_exception_messages(),
+ m_exception_messages_mutex(PTHREAD_MUTEX_RECURSIVE), m_thread_list(),
+ m_activities(), m_state(eStateUnloaded),
+ m_state_mutex(PTHREAD_MUTEX_RECURSIVE), m_events(0, kAllEventsMask),
+ m_private_events(0, kAllEventsMask), m_breakpoints(), m_watchpoints(),
+ m_name_to_addr_callback(NULL), m_name_to_addr_baton(NULL),
+ m_image_infos_callback(NULL), m_image_infos_baton(NULL),
+ m_sent_interrupt_signo(0), m_auto_resume_signo(0), m_did_exec(false),
+ m_dyld_process_info_create(nullptr),
+ m_dyld_process_info_for_each_image(nullptr),
+ m_dyld_process_info_release(nullptr),
+ m_dyld_process_info_get_cache(nullptr) {
+ m_dyld_process_info_create =
+ (void *(*)(task_t task, uint64_t timestamp, kern_return_t * kernelError))
+ dlsym(RTLD_DEFAULT, "_dyld_process_info_create");
+ m_dyld_process_info_for_each_image =
+ (void (*)(void *info, void (^)(uint64_t machHeaderAddress,
+ const uuid_t uuid, const char *path)))
+ dlsym(RTLD_DEFAULT, "_dyld_process_info_for_each_image");
+ m_dyld_process_info_release =
+ (void (*)(void *info))dlsym(RTLD_DEFAULT, "_dyld_process_info_release");
+ m_dyld_process_info_get_cache = (void (*)(void *info, void *cacheInfo))dlsym(
+ RTLD_DEFAULT, "_dyld_process_info_get_cache");
+
+ DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__);
+}
+
+MachProcess::~MachProcess() {
+ DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__);
+ Clear();
+}
+
+pid_t MachProcess::SetProcessID(pid_t pid) {
+ // Free any previous process specific data or resources
+ Clear();
+ // Set the current PID appropriately
+ if (pid == 0)
+ m_pid = ::getpid();
+ else
+ m_pid = pid;
+ return m_pid; // Return actually PID in case a zero pid was passed in
+}
+
+nub_state_t MachProcess::GetState() {
+ // If any other threads access this we will need a mutex for it
+ PTHREAD_MUTEX_LOCKER(locker, m_state_mutex);
+ return m_state;
+}
+
+const char *MachProcess::ThreadGetName(nub_thread_t tid) {
+ return m_thread_list.GetName(tid);
+}
+
+nub_state_t MachProcess::ThreadGetState(nub_thread_t tid) {
+ return m_thread_list.GetState(tid);
}
-nub_state_t
-MachProcess::ThreadGetState(nub_thread_t tid)
-{
- return m_thread_list.GetState(tid);
-}
-
-
-nub_size_t
-MachProcess::GetNumThreads () const
-{
- return m_thread_list.NumThreads();
+nub_size_t MachProcess::GetNumThreads() const {
+ return m_thread_list.NumThreads();
}
-nub_thread_t
-MachProcess::GetThreadAtIndex (nub_size_t thread_idx) const
-{
- return m_thread_list.ThreadIDAtIndex(thread_idx);
+nub_thread_t MachProcess::GetThreadAtIndex(nub_size_t thread_idx) const {
+ return m_thread_list.ThreadIDAtIndex(thread_idx);
}
nub_thread_t
-MachProcess::GetThreadIDForMachPortNumber (thread_t mach_port_number) const
-{
- return m_thread_list.GetThreadIDByMachPortNumber (mach_port_number);
+MachProcess::GetThreadIDForMachPortNumber(thread_t mach_port_number) const {
+ return m_thread_list.GetThreadIDByMachPortNumber(mach_port_number);
}
-nub_bool_t
-MachProcess::SyncThreadState (nub_thread_t tid)
-{
- MachThreadSP thread_sp(m_thread_list.GetThreadByID(tid));
- if (!thread_sp)
- return false;
- kern_return_t kret = ::thread_abort_safely(thread_sp->MachPortNumber());
- DNBLogThreadedIf (LOG_THREAD, "thread = 0x%8.8" PRIx32 " calling thread_abort_safely (tid) => %u (GetGPRState() for stop_count = %u)", thread_sp->MachPortNumber(), kret, thread_sp->Process()->StopCount());
+nub_bool_t MachProcess::SyncThreadState(nub_thread_t tid) {
+ MachThreadSP thread_sp(m_thread_list.GetThreadByID(tid));
+ if (!thread_sp)
+ return false;
+ kern_return_t kret = ::thread_abort_safely(thread_sp->MachPortNumber());
+ DNBLogThreadedIf(LOG_THREAD, "thread = 0x%8.8" PRIx32
+ " calling thread_abort_safely (tid) => %u "
+ "(GetGPRState() for stop_count = %u)",
+ thread_sp->MachPortNumber(), kret,
+ thread_sp->Process()->StopCount());
- if (kret == KERN_SUCCESS)
- return true;
- else
- return false;
-
+ if (kret == KERN_SUCCESS)
+ return true;
+ else
+ return false;
}
-ThreadInfo::QoS
-MachProcess::GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index)
-{
- return m_thread_list.GetRequestedQoS (tid, tsd, dti_qos_class_index);
+ThreadInfo::QoS MachProcess::GetRequestedQoS(nub_thread_t tid, nub_addr_t tsd,
+ uint64_t dti_qos_class_index) {
+ return m_thread_list.GetRequestedQoS(tid, tsd, dti_qos_class_index);
}
-nub_addr_t
-MachProcess::GetPThreadT (nub_thread_t tid)
-{
- return m_thread_list.GetPThreadT (tid);
+nub_addr_t MachProcess::GetPThreadT(nub_thread_t tid) {
+ return m_thread_list.GetPThreadT(tid);
}
-nub_addr_t
-MachProcess::GetDispatchQueueT (nub_thread_t tid)
-{
- return m_thread_list.GetDispatchQueueT (tid);
+nub_addr_t MachProcess::GetDispatchQueueT(nub_thread_t tid) {
+ return m_thread_list.GetDispatchQueueT(tid);
}
-nub_addr_t
-MachProcess::GetTSDAddressForThread (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)
-{
- return m_thread_list.GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
+nub_addr_t MachProcess::GetTSDAddressForThread(
+ 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) {
+ return m_thread_list.GetTSDAddressForThread(
+ tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset,
+ plo_pthread_tsd_entry_size);
}
-// Given an address, read the mach-o header and load commands out of memory to fill in
+// Given an address, read the mach-o header and load commands out of memory to
+// fill in
// the mach_o_information "inf" object.
//
-// Returns false if there was an error in reading this mach-o file header/load commands.
+// Returns false if there was an error in reading this mach-o file header/load
+// commands.
-bool
-MachProcess::GetMachOInformationFromMemory (nub_addr_t mach_o_header_addr, int wordsize, struct mach_o_information &inf)
-{
- uint64_t load_cmds_p;
- if (wordsize == 4)
- {
- struct mach_header header;
- if (ReadMemory (mach_o_header_addr, sizeof (struct mach_header), &header) != sizeof (struct mach_header))
- {
- return false;
- }
- load_cmds_p = mach_o_header_addr + sizeof (struct mach_header);
- inf.mach_header.magic = header.magic;
- inf.mach_header.cputype = header.cputype;
- // high byte of cpusubtype is used for "capability bits", v. CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h
- inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff;
- inf.mach_header.filetype = header.filetype;
- inf.mach_header.ncmds = header.ncmds;
- inf.mach_header.sizeofcmds = header.sizeofcmds;
- inf.mach_header.flags = header.flags;
+bool MachProcess::GetMachOInformationFromMemory(
+ nub_addr_t mach_o_header_addr, int wordsize,
+ struct mach_o_information &inf) {
+ uint64_t load_cmds_p;
+ if (wordsize == 4) {
+ struct mach_header header;
+ if (ReadMemory(mach_o_header_addr, sizeof(struct mach_header), &header) !=
+ sizeof(struct mach_header)) {
+ return false;
+ }
+ load_cmds_p = mach_o_header_addr + sizeof(struct mach_header);
+ inf.mach_header.magic = header.magic;
+ inf.mach_header.cputype = header.cputype;
+ // high byte of cpusubtype is used for "capability bits", v.
+ // CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h
+ inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff;
+ inf.mach_header.filetype = header.filetype;
+ inf.mach_header.ncmds = header.ncmds;
+ inf.mach_header.sizeofcmds = header.sizeofcmds;
+ inf.mach_header.flags = header.flags;
+ } else {
+ struct mach_header_64 header;
+ if (ReadMemory(mach_o_header_addr, sizeof(struct mach_header_64),
+ &header) != sizeof(struct mach_header_64)) {
+ return false;
+ }
+ load_cmds_p = mach_o_header_addr + sizeof(struct mach_header_64);
+ inf.mach_header.magic = header.magic;
+ inf.mach_header.cputype = header.cputype;
+ // high byte of cpusubtype is used for "capability bits", v.
+ // CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h
+ inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff;
+ inf.mach_header.filetype = header.filetype;
+ inf.mach_header.ncmds = header.ncmds;
+ inf.mach_header.sizeofcmds = header.sizeofcmds;
+ inf.mach_header.flags = header.flags;
+ }
+ for (uint32_t j = 0; j < inf.mach_header.ncmds; j++) {
+ struct load_command lc;
+ if (ReadMemory(load_cmds_p, sizeof(struct load_command), &lc) !=
+ sizeof(struct load_command)) {
+ return false;
+ }
+ if (lc.cmd == LC_SEGMENT) {
+ struct segment_command seg;
+ if (ReadMemory(load_cmds_p, sizeof(struct segment_command), &seg) !=
+ sizeof(struct segment_command)) {
+ return false;
+ }
+ struct mach_o_segment this_seg;
+ char name[17];
+ ::memset(name, 0, sizeof(name));
+ memcpy(name, seg.segname, sizeof(seg.segname));
+ this_seg.name = name;
+ this_seg.vmaddr = seg.vmaddr;
+ this_seg.vmsize = seg.vmsize;
+ this_seg.fileoff = seg.fileoff;
+ this_seg.filesize = seg.filesize;
+ this_seg.maxprot = seg.maxprot;
+ this_seg.initprot = seg.initprot;
+ this_seg.nsects = seg.nsects;
+ this_seg.flags = seg.flags;
+ inf.segments.push_back(this_seg);
+ }
+ if (lc.cmd == LC_SEGMENT_64) {
+ struct segment_command_64 seg;
+ if (ReadMemory(load_cmds_p, sizeof(struct segment_command_64), &seg) !=
+ sizeof(struct segment_command_64)) {
+ return false;
+ }
+ struct mach_o_segment this_seg;
+ char name[17];
+ ::memset(name, 0, sizeof(name));
+ memcpy(name, seg.segname, sizeof(seg.segname));
+ this_seg.name = name;
+ this_seg.vmaddr = seg.vmaddr;
+ this_seg.vmsize = seg.vmsize;
+ this_seg.fileoff = seg.fileoff;
+ this_seg.filesize = seg.filesize;
+ this_seg.maxprot = seg.maxprot;
+ this_seg.initprot = seg.initprot;
+ this_seg.nsects = seg.nsects;
+ this_seg.flags = seg.flags;
+ inf.segments.push_back(this_seg);
+ }
+ if (lc.cmd == LC_UUID) {
+ struct uuid_command uuidcmd;
+ if (ReadMemory(load_cmds_p, sizeof(struct uuid_command), &uuidcmd) ==
+ sizeof(struct uuid_command))
+ uuid_copy(inf.uuid, uuidcmd.uuid);
}
- else
- {
- struct mach_header_64 header;
- if (ReadMemory (mach_o_header_addr, sizeof (struct mach_header_64), &header) != sizeof (struct mach_header_64))
- {
- return false;
- }
- load_cmds_p = mach_o_header_addr + sizeof (struct mach_header_64);
- inf.mach_header.magic = header.magic;
- inf.mach_header.cputype = header.cputype;
- // high byte of cpusubtype is used for "capability bits", v. CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h
- inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff;
- inf.mach_header.filetype = header.filetype;
- inf.mach_header.ncmds = header.ncmds;
- inf.mach_header.sizeofcmds = header.sizeofcmds;
- inf.mach_header.flags = header.flags;
- }
- for (uint32_t j = 0; j < inf.mach_header.ncmds; j++)
- {
- struct load_command lc;
- if (ReadMemory (load_cmds_p, sizeof (struct load_command), &lc) != sizeof (struct load_command))
- {
- return false;
- }
- if (lc.cmd == LC_SEGMENT)
- {
- struct segment_command seg;
- if (ReadMemory (load_cmds_p, sizeof (struct segment_command), &seg) != sizeof (struct segment_command))
- {
- return false;
- }
- struct mach_o_segment this_seg;
- char name[17];
- ::memset (name, 0, sizeof (name));
- memcpy (name, seg.segname, sizeof (seg.segname));
- this_seg.name = name;
- this_seg.vmaddr = seg.vmaddr;
- this_seg.vmsize = seg.vmsize;
- this_seg.fileoff = seg.fileoff;
- this_seg.filesize = seg.filesize;
- this_seg.maxprot = seg.maxprot;
- this_seg.initprot = seg.initprot;
- this_seg.nsects = seg.nsects;
- this_seg.flags = seg.flags;
- inf.segments.push_back(this_seg);
- }
- if (lc.cmd == LC_SEGMENT_64)
- {
- struct segment_command_64 seg;
- if (ReadMemory (load_cmds_p, sizeof (struct segment_command_64), &seg) != sizeof (struct segment_command_64))
- {
- return false;
- }
- struct mach_o_segment this_seg;
- char name[17];
- ::memset (name, 0, sizeof (name));
- memcpy (name, seg.segname, sizeof (seg.segname));
- this_seg.name = name;
- this_seg.vmaddr = seg.vmaddr;
- this_seg.vmsize = seg.vmsize;
- this_seg.fileoff = seg.fileoff;
- this_seg.filesize = seg.filesize;
- this_seg.maxprot = seg.maxprot;
- this_seg.initprot = seg.initprot;
- this_seg.nsects = seg.nsects;
- this_seg.flags = seg.flags;
- inf.segments.push_back(this_seg);
- }
- if (lc.cmd == LC_UUID)
- {
- struct uuid_command uuidcmd;
- if (ReadMemory (load_cmds_p, sizeof (struct uuid_command), &uuidcmd) == sizeof (struct uuid_command))
- uuid_copy (inf.uuid, uuidcmd.uuid);
- }
- bool lc_cmd_known = lc.cmd == LC_VERSION_MIN_IPHONEOS || lc.cmd == LC_VERSION_MIN_MACOSX;
+ bool lc_cmd_known =
+ lc.cmd == LC_VERSION_MIN_IPHONEOS || lc.cmd == LC_VERSION_MIN_MACOSX;
#if defined(LC_VERSION_MIN_TVOS)
- lc_cmd_known |= lc.cmd == LC_VERSION_MIN_TVOS;
+ lc_cmd_known |= lc.cmd == LC_VERSION_MIN_TVOS;
#endif
#if defined(LC_VERSION_MIN_WATCHOS)
- lc_cmd_known |= lc.cmd == LC_VERSION_MIN_WATCHOS;
+ lc_cmd_known |= lc.cmd == LC_VERSION_MIN_WATCHOS;
#endif
- if (lc_cmd_known)
- {
- struct version_min_command vers_cmd;
- if (ReadMemory (load_cmds_p, sizeof (struct version_min_command), &vers_cmd) != sizeof (struct version_min_command))
- {
- return false;
- }
- switch (lc.cmd)
- {
- case LC_VERSION_MIN_IPHONEOS:
- inf.min_version_os_name = "iphoneos";
- break;
- case LC_VERSION_MIN_MACOSX:
- inf.min_version_os_name = "macosx";
- break;
+ if (lc_cmd_known) {
+ struct version_min_command vers_cmd;
+ if (ReadMemory(load_cmds_p, sizeof(struct version_min_command),
+ &vers_cmd) != sizeof(struct version_min_command)) {
+ return false;
+ }
+ switch (lc.cmd) {
+ case LC_VERSION_MIN_IPHONEOS:
+ inf.min_version_os_name = "iphoneos";
+ break;
+ case LC_VERSION_MIN_MACOSX:
+ inf.min_version_os_name = "macosx";
+ break;
#if defined(LC_VERSION_MIN_TVOS)
- case LC_VERSION_MIN_TVOS:
- inf.min_version_os_name = "tvos";
- break;
+ case LC_VERSION_MIN_TVOS:
+ inf.min_version_os_name = "tvos";
+ break;
#endif
#if defined(LC_VERSION_MIN_WATCHOS)
- case LC_VERSION_MIN_WATCHOS:
- inf.min_version_os_name = "watchos";
- break;
+ case LC_VERSION_MIN_WATCHOS:
+ inf.min_version_os_name = "watchos";
+ break;
#endif
- default:
- return false;
- }
- uint32_t xxxx = vers_cmd.sdk >> 16;
- uint32_t yy = (vers_cmd.sdk >> 8) & 0xffu;
- uint32_t zz = vers_cmd.sdk & 0xffu;
- inf.min_version_os_version = "";
- inf.min_version_os_version += std::to_string(xxxx);
- inf.min_version_os_version += ".";
- inf.min_version_os_version += std::to_string(yy);
- if (zz != 0)
- {
- inf.min_version_os_version += ".";
- inf.min_version_os_version += std::to_string(zz);
- }
- }
- load_cmds_p += lc.cmdsize;
- }
- return true;
+ default:
+ return false;
+ }
+ uint32_t xxxx = vers_cmd.sdk >> 16;
+ uint32_t yy = (vers_cmd.sdk >> 8) & 0xffu;
+ uint32_t zz = vers_cmd.sdk & 0xffu;
+ inf.min_version_os_version = "";
+ inf.min_version_os_version += std::to_string(xxxx);
+ inf.min_version_os_version += ".";
+ inf.min_version_os_version += std::to_string(yy);
+ if (zz != 0) {
+ inf.min_version_os_version += ".";
+ inf.min_version_os_version += std::to_string(zz);
+ }
+ }
+ load_cmds_p += lc.cmdsize;
+ }
+ return true;
}
-// Given completely filled in array of binary_image_information structures, create a JSONGenerator object
+// Given completely filled in array of binary_image_information structures,
+// create a JSONGenerator object
// with all the details we want to send to lldb.
-JSONGenerator::ObjectSP
-MachProcess::FormatDynamicLibrariesIntoJSON (const std::vector<struct binary_image_information> &image_infos)
-{
+JSONGenerator::ObjectSP MachProcess::FormatDynamicLibrariesIntoJSON(
+ const std::vector<struct binary_image_information> &image_infos) {
- JSONGenerator::ArraySP image_infos_array_sp (new JSONGenerator::Array());
+ JSONGenerator::ArraySP image_infos_array_sp(new JSONGenerator::Array());
- const size_t image_count = image_infos.size();
-
- for (size_t i = 0; i < image_count; i++)
- {
- JSONGenerator::DictionarySP image_info_dict_sp (new JSONGenerator::Dictionary());
- image_info_dict_sp->AddIntegerItem ("load_address", image_infos[i].load_address);
- image_info_dict_sp->AddIntegerItem ("mod_date", image_infos[i].mod_date);
- image_info_dict_sp->AddStringItem ("pathname", image_infos[i].filename);
-
- uuid_string_t uuidstr;
- uuid_unparse_upper (image_infos[i].macho_info.uuid, uuidstr);
- image_info_dict_sp->AddStringItem ("uuid", uuidstr);
-
- if (image_infos[i].macho_info.min_version_os_name.empty() == false
- && image_infos[i].macho_info.min_version_os_version.empty() == false)
- {
- image_info_dict_sp->AddStringItem ("min_version_os_name", image_infos[i].macho_info.min_version_os_name);
- image_info_dict_sp->AddStringItem ("min_version_os_sdk", image_infos[i].macho_info.min_version_os_version);
- }
-
- JSONGenerator::DictionarySP mach_header_dict_sp (new JSONGenerator::Dictionary());
- mach_header_dict_sp->AddIntegerItem ("magic", image_infos[i].macho_info.mach_header.magic);
- mach_header_dict_sp->AddIntegerItem ("cputype", (uint32_t) image_infos[i].macho_info.mach_header.cputype);
- mach_header_dict_sp->AddIntegerItem ("cpusubtype", (uint32_t) image_infos[i].macho_info.mach_header.cpusubtype);
- mach_header_dict_sp->AddIntegerItem ("filetype", image_infos[i].macho_info.mach_header.filetype);
-
-// DynamicLoaderMacOSX doesn't currently need these fields, so don't send them.
-// mach_header_dict_sp->AddIntegerItem ("ncmds", image_infos[i].macho_info.mach_header.ncmds);
-// mach_header_dict_sp->AddIntegerItem ("sizeofcmds", image_infos[i].macho_info.mach_header.sizeofcmds);
-// mach_header_dict_sp->AddIntegerItem ("flags", image_infos[i].macho_info.mach_header.flags);
- image_info_dict_sp->AddItem ("mach_header", mach_header_dict_sp);
-
- JSONGenerator::ArraySP segments_sp (new JSONGenerator::Array());
- for (size_t j = 0; j < image_infos[i].macho_info.segments.size(); j++)
- {
- JSONGenerator::DictionarySP segment_sp (new JSONGenerator::Dictionary());
- segment_sp->AddStringItem ("name", image_infos[i].macho_info.segments[j].name);
- segment_sp->AddIntegerItem ("vmaddr", image_infos[i].macho_info.segments[j].vmaddr);
- segment_sp->AddIntegerItem ("vmsize", image_infos[i].macho_info.segments[j].vmsize);
- segment_sp->AddIntegerItem ("fileoff", image_infos[i].macho_info.segments[j].fileoff);
- segment_sp->AddIntegerItem ("filesize", image_infos[i].macho_info.segments[j].filesize);
- segment_sp->AddIntegerItem ("maxprot", image_infos[i].macho_info.segments[j].maxprot);
-
-// DynamicLoaderMacOSX doesn't currently need these fields, so don't send them.
-// segment_sp->AddIntegerItem ("initprot", image_infos[i].macho_info.segments[j].initprot);
-// segment_sp->AddIntegerItem ("nsects", image_infos[i].macho_info.segments[j].nsects);
-// segment_sp->AddIntegerItem ("flags", image_infos[i].macho_info.segments[j].flags);
- segments_sp->AddItem (segment_sp);
- }
- image_info_dict_sp->AddItem ("segments", segments_sp);
-
- image_infos_array_sp->AddItem (image_info_dict_sp);
- }
+ const size_t image_count = image_infos.size();
- JSONGenerator::DictionarySP reply_sp (new JSONGenerator::Dictionary());;
- reply_sp->AddItem ("images", image_infos_array_sp);
+ for (size_t i = 0; i < image_count; i++) {
+ JSONGenerator::DictionarySP image_info_dict_sp(
+ new JSONGenerator::Dictionary());
+ image_info_dict_sp->AddIntegerItem("load_address",
+ image_infos[i].load_address);
+ image_info_dict_sp->AddIntegerItem("mod_date", image_infos[i].mod_date);
+ image_info_dict_sp->AddStringItem("pathname", image_infos[i].filename);
+
+ uuid_string_t uuidstr;
+ uuid_unparse_upper(image_infos[i].macho_info.uuid, uuidstr);
+ image_info_dict_sp->AddStringItem("uuid", uuidstr);
+
+ if (image_infos[i].macho_info.min_version_os_name.empty() == false &&
+ image_infos[i].macho_info.min_version_os_version.empty() == false) {
+ image_info_dict_sp->AddStringItem(
+ "min_version_os_name", image_infos[i].macho_info.min_version_os_name);
+ image_info_dict_sp->AddStringItem(
+ "min_version_os_sdk",
+ image_infos[i].macho_info.min_version_os_version);
+ }
+
+ JSONGenerator::DictionarySP mach_header_dict_sp(
+ new JSONGenerator::Dictionary());
+ mach_header_dict_sp->AddIntegerItem(
+ "magic", image_infos[i].macho_info.mach_header.magic);
+ mach_header_dict_sp->AddIntegerItem(
+ "cputype", (uint32_t)image_infos[i].macho_info.mach_header.cputype);
+ mach_header_dict_sp->AddIntegerItem(
+ "cpusubtype",
+ (uint32_t)image_infos[i].macho_info.mach_header.cpusubtype);
+ mach_header_dict_sp->AddIntegerItem(
+ "filetype", image_infos[i].macho_info.mach_header.filetype);
+
+ // DynamicLoaderMacOSX doesn't currently need these fields, so
+ // don't send them.
+ // mach_header_dict_sp->AddIntegerItem ("ncmds",
+ // image_infos[i].macho_info.mach_header.ncmds);
+ // mach_header_dict_sp->AddIntegerItem ("sizeofcmds",
+ // image_infos[i].macho_info.mach_header.sizeofcmds);
+ // mach_header_dict_sp->AddIntegerItem ("flags",
+ // image_infos[i].macho_info.mach_header.flags);
+ image_info_dict_sp->AddItem("mach_header", mach_header_dict_sp);
+
+ JSONGenerator::ArraySP segments_sp(new JSONGenerator::Array());
+ for (size_t j = 0; j < image_infos[i].macho_info.segments.size(); j++) {
+ JSONGenerator::DictionarySP segment_sp(new JSONGenerator::Dictionary());
+ segment_sp->AddStringItem("name",
+ image_infos[i].macho_info.segments[j].name);
+ segment_sp->AddIntegerItem("vmaddr",
+ image_infos[i].macho_info.segments[j].vmaddr);
+ segment_sp->AddIntegerItem("vmsize",
+ image_infos[i].macho_info.segments[j].vmsize);
+ segment_sp->AddIntegerItem("fileoff",
+ image_infos[i].macho_info.segments[j].fileoff);
+ segment_sp->AddIntegerItem(
+ "filesize", image_infos[i].macho_info.segments[j].filesize);
+ segment_sp->AddIntegerItem("maxprot",
+ image_infos[i].macho_info.segments[j].maxprot);
+
+ // DynamicLoaderMacOSX doesn't currently need these fields,
+ // so don't send them.
+ // segment_sp->AddIntegerItem ("initprot",
+ // image_infos[i].macho_info.segments[j].initprot);
+ // segment_sp->AddIntegerItem ("nsects",
+ // image_infos[i].macho_info.segments[j].nsects);
+ // segment_sp->AddIntegerItem ("flags",
+ // image_infos[i].macho_info.segments[j].flags);
+ segments_sp->AddItem(segment_sp);
+ }
+ image_info_dict_sp->AddItem("segments", segments_sp);
+
+ image_infos_array_sp->AddItem(image_info_dict_sp);
+ }
+
+ JSONGenerator::DictionarySP reply_sp(new JSONGenerator::Dictionary());
+ ;
+ reply_sp->AddItem("images", image_infos_array_sp);
- return reply_sp;
+ return reply_sp;
}
-// Get the shared library information using the old (pre-macOS 10.12, pre-iOS 10, pre-tvOS 10, pre-watchOS 3)
+// Get the shared library information using the old (pre-macOS 10.12, pre-iOS
+// 10, pre-tvOS 10, pre-watchOS 3)
// code path. We'll be given the address of an array of structures in the form
-// {void* load_addr, void* mod_date, void* pathname}
+// {void* load_addr, void* mod_date, void* pathname}
//
-// In macOS 10.12 etc and newer, we'll use SPI calls into dyld to gather this information.
-JSONGenerator::ObjectSP
-MachProcess::GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count)
-{
- JSONGenerator::DictionarySP reply_sp;
-
- int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
- struct kinfo_proc processInfo;
- size_t bufsize = sizeof(processInfo);
- if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0)
- {
- uint32_t pointer_size = 4;
- if (processInfo.kp_proc.p_flag & P_LP64)
- pointer_size = 8;
-
- std::vector<struct binary_image_information> image_infos;
- size_t image_infos_size = image_count * 3 * pointer_size;
-
- uint8_t *image_info_buf = (uint8_t *) malloc (image_infos_size);
- if (image_info_buf == NULL)
- {
- return reply_sp;
- }
- if (ReadMemory (image_list_address, image_infos_size, image_info_buf) != image_infos_size)
- {
- return reply_sp;
- }
-
-
- //// First the image_infos array with (load addr, pathname, mod date) tuples
-
-
- for (size_t i = 0; i < image_count; i++)
- {
- struct binary_image_information info;
- nub_addr_t pathname_address;
- if (pointer_size == 4)
- {
- uint32_t load_address_32;
- uint32_t pathname_address_32;
- uint32_t mod_date_32;
- ::memcpy (&load_address_32, image_info_buf + (i * 3 * pointer_size), 4);
- ::memcpy (&pathname_address_32, image_info_buf + (i * 3 * pointer_size) + pointer_size, 4);
- ::memcpy (&mod_date_32, image_info_buf + (i * 3 * pointer_size) + pointer_size + pointer_size, 4);
- info.load_address = load_address_32;
- info.mod_date = mod_date_32;
- pathname_address = pathname_address_32;
- }
- else
- {
- uint64_t load_address_64;
- uint64_t pathname_address_64;
- uint64_t mod_date_64;
- ::memcpy (&load_address_64, image_info_buf + (i * 3 * pointer_size), 8);
- ::memcpy (&pathname_address_64, image_info_buf + (i * 3 * pointer_size) + pointer_size, 8);
- ::memcpy (&mod_date_64, image_info_buf + (i * 3 * pointer_size) + pointer_size + pointer_size, 8);
- info.load_address = load_address_64;
- info.mod_date = mod_date_64;
- pathname_address = pathname_address_64;
- }
- char strbuf[17];
- info.filename = "";
- uint64_t pathname_ptr = pathname_address;
- bool still_reading = true;
- while (still_reading && ReadMemory (pathname_ptr, sizeof (strbuf) - 1, strbuf) == sizeof (strbuf) - 1)
- {
- strbuf[sizeof(strbuf) - 1] = '\0';
- info.filename += strbuf;
- pathname_ptr += sizeof (strbuf) - 1;
- // Stop if we found nul byte indicating the end of the string
- for (size_t i = 0; i < sizeof(strbuf) - 1; i++)
- {
- if (strbuf[i] == '\0')
- {
- still_reading = false;
- break;
- }
- }
- }
- uuid_clear (info.macho_info.uuid);
- image_infos.push_back (info);
- }
- if (image_infos.size() == 0)
- {
- return reply_sp;
+// In macOS 10.12 etc and newer, we'll use SPI calls into dyld to gather this
+// information.
+JSONGenerator::ObjectSP MachProcess::GetLoadedDynamicLibrariesInfos(
+ nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) {
+ JSONGenerator::DictionarySP reply_sp;
+
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
+ struct kinfo_proc processInfo;
+ size_t bufsize = sizeof(processInfo);
+ if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize,
+ NULL, 0) == 0 &&
+ bufsize > 0) {
+ uint32_t pointer_size = 4;
+ if (processInfo.kp_proc.p_flag & P_LP64)
+ pointer_size = 8;
+
+ std::vector<struct binary_image_information> image_infos;
+ size_t image_infos_size = image_count * 3 * pointer_size;
+
+ uint8_t *image_info_buf = (uint8_t *)malloc(image_infos_size);
+ if (image_info_buf == NULL) {
+ return reply_sp;
+ }
+ if (ReadMemory(image_list_address, image_infos_size, image_info_buf) !=
+ image_infos_size) {
+ return reply_sp;
+ }
+
+ //// First the image_infos array with (load addr, pathname, mod date)
+ ///tuples
+
+ for (size_t i = 0; i < image_count; i++) {
+ struct binary_image_information info;
+ nub_addr_t pathname_address;
+ if (pointer_size == 4) {
+ uint32_t load_address_32;
+ uint32_t pathname_address_32;
+ uint32_t mod_date_32;
+ ::memcpy(&load_address_32, image_info_buf + (i * 3 * pointer_size), 4);
+ ::memcpy(&pathname_address_32,
+ image_info_buf + (i * 3 * pointer_size) + pointer_size, 4);
+ ::memcpy(&mod_date_32, image_info_buf + (i * 3 * pointer_size) +
+ pointer_size + pointer_size,
+ 4);
+ info.load_address = load_address_32;
+ info.mod_date = mod_date_32;
+ pathname_address = pathname_address_32;
+ } else {
+ uint64_t load_address_64;
+ uint64_t pathname_address_64;
+ uint64_t mod_date_64;
+ ::memcpy(&load_address_64, image_info_buf + (i * 3 * pointer_size), 8);
+ ::memcpy(&pathname_address_64,
+ image_info_buf + (i * 3 * pointer_size) + pointer_size, 8);
+ ::memcpy(&mod_date_64, image_info_buf + (i * 3 * pointer_size) +
+ pointer_size + pointer_size,
+ 8);
+ info.load_address = load_address_64;
+ info.mod_date = mod_date_64;
+ pathname_address = pathname_address_64;
+ }
+ char strbuf[17];
+ info.filename = "";
+ uint64_t pathname_ptr = pathname_address;
+ bool still_reading = true;
+ while (still_reading &&
+ ReadMemory(pathname_ptr, sizeof(strbuf) - 1, strbuf) ==
+ sizeof(strbuf) - 1) {
+ strbuf[sizeof(strbuf) - 1] = '\0';
+ info.filename += strbuf;
+ pathname_ptr += sizeof(strbuf) - 1;
+ // Stop if we found nul byte indicating the end of the string
+ for (size_t i = 0; i < sizeof(strbuf) - 1; i++) {
+ if (strbuf[i] == '\0') {
+ still_reading = false;
+ break;
+ }
}
+ }
+ uuid_clear(info.macho_info.uuid);
+ image_infos.push_back(info);
+ }
+ if (image_infos.size() == 0) {
+ return reply_sp;
+ }
- free (image_info_buf);
-
- //// Second, read the mach header / load commands for all the dylibs
-
- for (size_t i = 0; i < image_count; i++)
- {
- if (!GetMachOInformationFromMemory (image_infos[i].load_address, pointer_size, image_infos[i].macho_info))
- {
- return reply_sp;
- }
- }
+ free(image_info_buf);
+ //// Second, read the mach header / load commands for all the dylibs
- //// Third, format all of the above in the JSONGenerator object.
+ for (size_t i = 0; i < image_count; i++) {
+ if (!GetMachOInformationFromMemory(image_infos[i].load_address,
+ pointer_size,
+ image_infos[i].macho_info)) {
+ return reply_sp;
+ }
+ }
+ //// Third, format all of the above in the JSONGenerator object.
- return FormatDynamicLibrariesIntoJSON (image_infos);
- }
+ return FormatDynamicLibrariesIntoJSON(image_infos);
+ }
- return reply_sp;
+ return reply_sp;
}
// From dyld SPI header dyld_process_info.h
-typedef void* dyld_process_info;
-struct dyld_process_cache_info
-{
- uuid_t cacheUUID; // UUID of cache used by process
- uint64_t cacheBaseAddress; // load address of dyld shared cache
- bool noCache; // process is running without a dyld cache
- bool privateCache; // process is using a private copy of its dyld cache
+typedef void *dyld_process_info;
+struct dyld_process_cache_info {
+ uuid_t cacheUUID; // UUID of cache used by process
+ uint64_t cacheBaseAddress; // load address of dyld shared cache
+ bool noCache; // process is running without a dyld cache
+ bool privateCache; // process is using a private copy of its dyld cache
};
-
-// Use the dyld SPI present in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer to get
+// Use the dyld SPI present in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer
+// to get
// the load address, uuid, and filenames of all the libraries.
-// This only fills in those three fields in the 'struct binary_image_information' - call
-// GetMachOInformationFromMemory to fill in the mach-o header/load command details.
-void
-MachProcess::GetAllLoadedBinariesViaDYLDSPI (std::vector<struct binary_image_information> &image_infos)
-{
- kern_return_t kern_ret;
- if (m_dyld_process_info_create)
- {
- dyld_process_info info = m_dyld_process_info_create (m_task.TaskPort(), 0, &kern_ret);
- if (info)
- {
- m_dyld_process_info_for_each_image (info, ^(uint64_t mach_header_addr, const uuid_t uuid, const char *path) {
- struct binary_image_information image;
- image.filename = path;
- uuid_copy (image.macho_info.uuid, uuid);
- image.load_address = mach_header_addr;
- image_infos.push_back (image);
- });
- m_dyld_process_info_release (info);
- }
+// This only fills in those three fields in the 'struct
+// binary_image_information' - call
+// GetMachOInformationFromMemory to fill in the mach-o header/load command
+// details.
+void MachProcess::GetAllLoadedBinariesViaDYLDSPI(
+ std::vector<struct binary_image_information> &image_infos) {
+ kern_return_t kern_ret;
+ if (m_dyld_process_info_create) {
+ dyld_process_info info =
+ m_dyld_process_info_create(m_task.TaskPort(), 0, &kern_ret);
+ if (info) {
+ m_dyld_process_info_for_each_image(
+ info,
+ ^(uint64_t mach_header_addr, const uuid_t uuid, const char *path) {
+ struct binary_image_information image;
+ image.filename = path;
+ uuid_copy(image.macho_info.uuid, uuid);
+ image.load_address = mach_header_addr;
+ image_infos.push_back(image);
+ });
+ m_dyld_process_info_release(info);
}
+ }
}
-// Fetch information about all shared libraries using the dyld SPIs that exist in
+// Fetch information about all shared libraries using the dyld SPIs that exist
+// in
// macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer.
-JSONGenerator::ObjectSP
-MachProcess::GetAllLoadedLibrariesInfos (nub_process_t pid)
-{
- JSONGenerator::DictionarySP reply_sp;
-
- int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
- struct kinfo_proc processInfo;
- size_t bufsize = sizeof(processInfo);
- if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0)
- {
- uint32_t pointer_size = 4;
- if (processInfo.kp_proc.p_flag & P_LP64)
- pointer_size = 8;
-
- std::vector<struct binary_image_information> image_infos;
- GetAllLoadedBinariesViaDYLDSPI (image_infos);
- const size_t image_count = image_infos.size();
- for (size_t i = 0; i < image_count; i++)
- {
- GetMachOInformationFromMemory (image_infos[i].load_address, pointer_size, image_infos[i].macho_info);
- }
- return FormatDynamicLibrariesIntoJSON (image_infos);
+JSONGenerator::ObjectSP
+MachProcess::GetAllLoadedLibrariesInfos(nub_process_t pid) {
+ JSONGenerator::DictionarySP reply_sp;
+
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
+ struct kinfo_proc processInfo;
+ size_t bufsize = sizeof(processInfo);
+ if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize,
+ NULL, 0) == 0 &&
+ bufsize > 0) {
+ uint32_t pointer_size = 4;
+ if (processInfo.kp_proc.p_flag & P_LP64)
+ pointer_size = 8;
+
+ std::vector<struct binary_image_information> image_infos;
+ GetAllLoadedBinariesViaDYLDSPI(image_infos);
+ const size_t image_count = image_infos.size();
+ for (size_t i = 0; i < image_count; i++) {
+ GetMachOInformationFromMemory(image_infos[i].load_address, pointer_size,
+ image_infos[i].macho_info);
}
- return reply_sp;
+ return FormatDynamicLibrariesIntoJSON(image_infos);
+ }
+ return reply_sp;
}
-// Fetch information about the shared libraries at the given load addresses using the
+// Fetch information about the shared libraries at the given load addresses
+// using the
// dyld SPIs that exist in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer.
-JSONGenerator::ObjectSP
-MachProcess::GetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses)
-{
- JSONGenerator::DictionarySP reply_sp;
-
- int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
- struct kinfo_proc processInfo;
- size_t bufsize = sizeof(processInfo);
- if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0)
- {
- uint32_t pointer_size = 4;
- if (processInfo.kp_proc.p_flag & P_LP64)
- pointer_size = 8;
-
- std::vector<struct binary_image_information> all_image_infos;
- GetAllLoadedBinariesViaDYLDSPI (all_image_infos);
-
- std::vector<struct binary_image_information> image_infos;
- const size_t macho_addresses_count = macho_addresses.size();
- const size_t all_image_infos_count = all_image_infos.size();
- for (size_t i = 0; i < macho_addresses_count; i++)
- {
- for (size_t j = 0; j < all_image_infos_count; j++)
- {
- if (all_image_infos[j].load_address == macho_addresses[i])
- {
- image_infos.push_back (all_image_infos[j]);
- }
- }
- }
-
- const size_t image_infos_count = image_infos.size();
- for (size_t i = 0; i < image_infos_count; i++)
- {
- GetMachOInformationFromMemory (image_infos[i].load_address, pointer_size, image_infos[i].macho_info);
- }
- return FormatDynamicLibrariesIntoJSON (image_infos);
- }
- return reply_sp;
+JSONGenerator::ObjectSP MachProcess::GetLibrariesInfoForAddresses(
+ nub_process_t pid, std::vector<uint64_t> &macho_addresses) {
+ JSONGenerator::DictionarySP reply_sp;
+
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
+ struct kinfo_proc processInfo;
+ size_t bufsize = sizeof(processInfo);
+ if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize,
+ NULL, 0) == 0 &&
+ bufsize > 0) {
+ uint32_t pointer_size = 4;
+ if (processInfo.kp_proc.p_flag & P_LP64)
+ pointer_size = 8;
+
+ std::vector<struct binary_image_information> all_image_infos;
+ GetAllLoadedBinariesViaDYLDSPI(all_image_infos);
+
+ std::vector<struct binary_image_information> image_infos;
+ const size_t macho_addresses_count = macho_addresses.size();
+ const size_t all_image_infos_count = all_image_infos.size();
+ for (size_t i = 0; i < macho_addresses_count; i++) {
+ for (size_t j = 0; j < all_image_infos_count; j++) {
+ if (all_image_infos[j].load_address == macho_addresses[i]) {
+ image_infos.push_back(all_image_infos[j]);
+ }
+ }
+ }
+
+ const size_t image_infos_count = image_infos.size();
+ for (size_t i = 0; i < image_infos_count; i++) {
+ GetMachOInformationFromMemory(image_infos[i].load_address, pointer_size,
+ image_infos[i].macho_info);
+ }
+ return FormatDynamicLibrariesIntoJSON(image_infos);
+ }
+ return reply_sp;
}
// From dyld's internal podyld_process_info.h:
-JSONGenerator::ObjectSP
-MachProcess::GetSharedCacheInfo (nub_process_t pid)
-{
- JSONGenerator::DictionarySP reply_sp (new JSONGenerator::Dictionary());;
- kern_return_t kern_ret;
- if (m_dyld_process_info_create && m_dyld_process_info_get_cache)
- {
- dyld_process_info info = m_dyld_process_info_create (m_task.TaskPort(), 0, &kern_ret);
- if (info)
- {
- struct dyld_process_cache_info shared_cache_info;
- m_dyld_process_info_get_cache (info, &shared_cache_info);
-
- reply_sp->AddIntegerItem ("shared_cache_base_address", shared_cache_info.cacheBaseAddress);
-
- uuid_string_t uuidstr;
- uuid_unparse_upper (shared_cache_info.cacheUUID, uuidstr);
- reply_sp->AddStringItem ("shared_cache_uuid", uuidstr);
-
- reply_sp->AddBooleanItem ("no_shared_cache", shared_cache_info.noCache);
- reply_sp->AddBooleanItem ("shared_cache_private_cache", shared_cache_info.privateCache);
+JSONGenerator::ObjectSP MachProcess::GetSharedCacheInfo(nub_process_t pid) {
+ JSONGenerator::DictionarySP reply_sp(new JSONGenerator::Dictionary());
+ ;
+ kern_return_t kern_ret;
+ if (m_dyld_process_info_create && m_dyld_process_info_get_cache) {
+ dyld_process_info info =
+ m_dyld_process_info_create(m_task.TaskPort(), 0, &kern_ret);
+ if (info) {
+ struct dyld_process_cache_info shared_cache_info;
+ m_dyld_process_info_get_cache(info, &shared_cache_info);
- m_dyld_process_info_release (info);
- }
+ reply_sp->AddIntegerItem("shared_cache_base_address",
+ shared_cache_info.cacheBaseAddress);
+
+ uuid_string_t uuidstr;
+ uuid_unparse_upper(shared_cache_info.cacheUUID, uuidstr);
+ reply_sp->AddStringItem("shared_cache_uuid", uuidstr);
+
+ reply_sp->AddBooleanItem("no_shared_cache", shared_cache_info.noCache);
+ reply_sp->AddBooleanItem("shared_cache_private_cache",
+ shared_cache_info.privateCache);
+
+ m_dyld_process_info_release(info);
}
- return reply_sp;
+ }
+ return reply_sp;
}
-nub_thread_t
-MachProcess::GetCurrentThread ()
-{
- return m_thread_list.CurrentThreadID();
+nub_thread_t MachProcess::GetCurrentThread() {
+ return m_thread_list.CurrentThreadID();
}
-nub_thread_t
-MachProcess::GetCurrentThreadMachPort ()
-{
- return m_thread_list.GetMachPortNumberByThreadID(m_thread_list.CurrentThreadID());
+nub_thread_t MachProcess::GetCurrentThreadMachPort() {
+ return m_thread_list.GetMachPortNumberByThreadID(
+ m_thread_list.CurrentThreadID());
}
-nub_thread_t
-MachProcess::SetCurrentThread(nub_thread_t tid)
-{
- return m_thread_list.SetCurrentThread(tid);
+nub_thread_t MachProcess::SetCurrentThread(nub_thread_t tid) {
+ return m_thread_list.SetCurrentThread(tid);
}
-bool
-MachProcess::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
-{
- if (m_thread_list.GetThreadStoppedReason(tid, stop_info))
- {
- if (m_did_exec)
- stop_info->reason = eStopTypeExec;
- return true;
- }
- return false;
+bool MachProcess::GetThreadStoppedReason(nub_thread_t tid,
+ struct DNBThreadStopInfo *stop_info) {
+ if (m_thread_list.GetThreadStoppedReason(tid, stop_info)) {
+ if (m_did_exec)
+ stop_info->reason = eStopTypeExec;
+ return true;
+ }
+ return false;
}
-void
-MachProcess::DumpThreadStoppedReason(nub_thread_t tid) const
-{
- return m_thread_list.DumpThreadStoppedReason(tid);
-}
-
-const char *
-MachProcess::GetThreadInfo(nub_thread_t tid) const
-{
- return m_thread_list.GetThreadInfo(tid);
-}
-
-uint32_t
-MachProcess::GetCPUType ()
-{
- if (m_cpu_type == 0 && m_pid != 0)
- m_cpu_type = MachProcess::GetCPUTypeForLocalProcess (m_pid);
- return m_cpu_type;
+void MachProcess::DumpThreadStoppedReason(nub_thread_t tid) const {
+ return m_thread_list.DumpThreadStoppedReason(tid);
}
-const DNBRegisterSetInfo *
-MachProcess::GetRegisterSetInfo (nub_thread_t tid, nub_size_t *num_reg_sets) const
-{
- MachThreadSP thread_sp (m_thread_list.GetThreadByID (tid));
- if (thread_sp)
- {
- DNBArchProtocol *arch = thread_sp->GetArchProtocol();
- if (arch)
- return arch->GetRegisterSetInfo (num_reg_sets);
- }
- *num_reg_sets = 0;
- return NULL;
+const char *MachProcess::GetThreadInfo(nub_thread_t tid) const {
+ return m_thread_list.GetThreadInfo(tid);
}
-bool
-MachProcess::GetRegisterValue ( nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value ) const
-{
- return m_thread_list.GetRegisterValue(tid, set, reg, value);
-}
-
-bool
-MachProcess::SetRegisterValue ( nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value ) const
-{
- return m_thread_list.SetRegisterValue(tid, set, reg, value);
-}
-
-void
-MachProcess::SetState(nub_state_t new_state)
-{
- // If any other threads access this we will need a mutex for it
- uint32_t event_mask = 0;
-
- // Scope for mutex locker
- {
- PTHREAD_MUTEX_LOCKER(locker, m_state_mutex);
- const nub_state_t old_state = m_state;
-
- if (old_state == eStateExited)
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState(%s) ignoring new state since current state is exited", DNBStateAsString(new_state));
- }
- else if (old_state == new_state)
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState(%s) ignoring redundant state change...", DNBStateAsString(new_state));
- }
- else
- {
- if (NUB_STATE_IS_STOPPED(new_state))
- event_mask = eEventProcessStoppedStateChanged;
- else
- event_mask = eEventProcessRunningStateChanged;
-
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState(%s) upating state (previous state was %s), event_mask = 0x%8.8x", DNBStateAsString(new_state), DNBStateAsString(old_state), event_mask);
-
- m_state = new_state;
- if (new_state == eStateStopped)
- m_stop_count++;
- }
- }
-
- if (event_mask != 0)
- {
- m_events.SetEvents (event_mask);
- m_private_events.SetEvents (event_mask);
- if (event_mask == eEventProcessStoppedStateChanged)
- m_private_events.ResetEvents (eEventProcessRunningStateChanged);
- else
- m_private_events.ResetEvents (eEventProcessStoppedStateChanged);
-
- // Wait for the event bit to reset if a reset ACK is requested
- m_events.WaitForResetAck(event_mask);
- }
-
+uint32_t MachProcess::GetCPUType() {
+ if (m_cpu_type == 0 && m_pid != 0)
+ m_cpu_type = MachProcess::GetCPUTypeForLocalProcess(m_pid);
+ return m_cpu_type;
}
-void
-MachProcess::Clear(bool detaching)
-{
- // Clear any cached thread list while the pid and task are still valid
-
- m_task.Clear();
- // Now clear out all member variables
- m_pid = INVALID_NUB_PROCESS;
- if (!detaching)
- CloseChildFileDescriptors();
-
- m_path.clear();
- m_args.clear();
- SetState(eStateUnloaded);
- m_flags = eMachProcessFlagsNone;
- m_stop_count = 0;
- m_thread_list.Clear();
- {
- PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
- m_exception_messages.clear();
- }
- m_activities.Clear();
- if (m_profile_thread)
- {
- pthread_join(m_profile_thread, NULL);
- m_profile_thread = NULL;
- }
+const DNBRegisterSetInfo *
+MachProcess::GetRegisterSetInfo(nub_thread_t tid,
+ nub_size_t *num_reg_sets) const {
+ MachThreadSP thread_sp(m_thread_list.GetThreadByID(tid));
+ if (thread_sp) {
+ DNBArchProtocol *arch = thread_sp->GetArchProtocol();
+ if (arch)
+ return arch->GetRegisterSetInfo(num_reg_sets);
+ }
+ *num_reg_sets = 0;
+ return NULL;
}
-
-bool
-MachProcess::StartSTDIOThread()
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( )", __FUNCTION__);
- // Create the thread that watches for the child STDIO
- return ::pthread_create (&m_stdio_thread, NULL, MachProcess::STDIOThread, this) == 0;
+bool MachProcess::GetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg,
+ DNBRegisterValue *value) const {
+ return m_thread_list.GetRegisterValue(tid, set, reg, value);
}
-void
-MachProcess::SetEnableAsyncProfiling(bool enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
-{
- m_profile_enabled = enable;
- m_profile_interval_usec = static_cast<useconds_t>(interval_usec);
- m_profile_scan_type = scan_type;
-
- if (m_profile_enabled && (m_profile_thread == NULL))
- {
- StartProfileThread();
- }
- else if (!m_profile_enabled && m_profile_thread)
- {
- pthread_join(m_profile_thread, NULL);
- m_profile_thread = NULL;
- }
+bool MachProcess::SetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg,
+ const DNBRegisterValue *value) const {
+ return m_thread_list.SetRegisterValue(tid, set, reg, value);
}
-bool
-MachProcess::StartProfileThread()
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( )", __FUNCTION__);
- // Create the thread that profiles the inferior and reports back if enabled
- return ::pthread_create (&m_profile_thread, NULL, MachProcess::ProfileThread, this) == 0;
-}
+void MachProcess::SetState(nub_state_t new_state) {
+ // If any other threads access this we will need a mutex for it
+ uint32_t event_mask = 0;
+ // Scope for mutex locker
+ {
+ PTHREAD_MUTEX_LOCKER(locker, m_state_mutex);
+ const nub_state_t old_state = m_state;
+
+ if (old_state == eStateExited) {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState(%s) ignoring new "
+ "state since current state is exited",
+ DNBStateAsString(new_state));
+ } else if (old_state == new_state) {
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "MachProcess::SetState(%s) ignoring redundant state change...",
+ DNBStateAsString(new_state));
+ } else {
+ if (NUB_STATE_IS_STOPPED(new_state))
+ event_mask = eEventProcessStoppedStateChanged;
+ else
+ event_mask = eEventProcessRunningStateChanged;
+
+ DNBLogThreadedIf(
+ LOG_PROCESS, "MachProcess::SetState(%s) upating state (previous "
+ "state was %s), event_mask = 0x%8.8x",
+ DNBStateAsString(new_state), DNBStateAsString(old_state), event_mask);
+
+ m_state = new_state;
+ if (new_state == eStateStopped)
+ m_stop_count++;
+ }
+ }
+
+ if (event_mask != 0) {
+ m_events.SetEvents(event_mask);
+ m_private_events.SetEvents(event_mask);
+ if (event_mask == eEventProcessStoppedStateChanged)
+ m_private_events.ResetEvents(eEventProcessRunningStateChanged);
+ else
+ m_private_events.ResetEvents(eEventProcessStoppedStateChanged);
-nub_addr_t
-MachProcess::LookupSymbol(const char *name, const char *shlib)
-{
- if (m_name_to_addr_callback != NULL && name && name[0])
- return m_name_to_addr_callback(ProcessID(), name, shlib, m_name_to_addr_baton);
- return INVALID_NUB_ADDRESS;
+ // Wait for the event bit to reset if a reset ACK is requested
+ m_events.WaitForResetAck(event_mask);
+ }
}
-bool
-MachProcess::Resume (const DNBThreadResumeActions& thread_actions)
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Resume ()");
- nub_state_t state = GetState();
+void MachProcess::Clear(bool detaching) {
+ // Clear any cached thread list while the pid and task are still valid
- if (CanResume(state))
- {
- m_thread_actions = thread_actions;
- PrivateResume();
- return true;
- }
- else if (state == eStateRunning)
- {
- DNBLog("Resume() - task 0x%x is already running, ignoring...", m_task.TaskPort());
+ m_task.Clear();
+ // Now clear out all member variables
+ m_pid = INVALID_NUB_PROCESS;
+ if (!detaching)
+ CloseChildFileDescriptors();
+
+ m_path.clear();
+ m_args.clear();
+ SetState(eStateUnloaded);
+ m_flags = eMachProcessFlagsNone;
+ m_stop_count = 0;
+ m_thread_list.Clear();
+ {
+ PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
+ m_exception_messages.clear();
+ }
+ m_activities.Clear();
+ if (m_profile_thread) {
+ pthread_join(m_profile_thread, NULL);
+ m_profile_thread = NULL;
+ }
+}
+
+bool MachProcess::StartSTDIOThread() {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( )", __FUNCTION__);
+ // Create the thread that watches for the child STDIO
+ return ::pthread_create(&m_stdio_thread, NULL, MachProcess::STDIOThread,
+ this) == 0;
+}
+
+void MachProcess::SetEnableAsyncProfiling(bool enable, uint64_t interval_usec,
+ DNBProfileDataScanType scan_type) {
+ m_profile_enabled = enable;
+ m_profile_interval_usec = static_cast<useconds_t>(interval_usec);
+ m_profile_scan_type = scan_type;
+
+ if (m_profile_enabled && (m_profile_thread == NULL)) {
+ StartProfileThread();
+ } else if (!m_profile_enabled && m_profile_thread) {
+ pthread_join(m_profile_thread, NULL);
+ m_profile_thread = NULL;
+ }
+}
+
+bool MachProcess::StartProfileThread() {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( )", __FUNCTION__);
+ // Create the thread that profiles the inferior and reports back if enabled
+ return ::pthread_create(&m_profile_thread, NULL, MachProcess::ProfileThread,
+ this) == 0;
+}
+
+nub_addr_t MachProcess::LookupSymbol(const char *name, const char *shlib) {
+ if (m_name_to_addr_callback != NULL && name && name[0])
+ return m_name_to_addr_callback(ProcessID(), name, shlib,
+ m_name_to_addr_baton);
+ return INVALID_NUB_ADDRESS;
+}
+
+bool MachProcess::Resume(const DNBThreadResumeActions &thread_actions) {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Resume ()");
+ nub_state_t state = GetState();
+
+ if (CanResume(state)) {
+ m_thread_actions = thread_actions;
+ PrivateResume();
+ return true;
+ } else if (state == eStateRunning) {
+ DNBLog("Resume() - task 0x%x is already running, ignoring...",
+ m_task.TaskPort());
+ return true;
+ }
+ DNBLog("Resume() - task 0x%x has state %s, can't continue...",
+ m_task.TaskPort(), DNBStateAsString(state));
+ return false;
+}
+
+bool MachProcess::Kill(const struct timespec *timeout_abstime) {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill ()");
+ nub_state_t state = DoSIGSTOP(true, false, NULL);
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() state = %s",
+ DNBStateAsString(state));
+ errno = 0;
+ DNBLog("Sending ptrace PT_KILL to terminate inferior process.");
+ ::ptrace(PT_KILL, m_pid, 0, 0);
+ DNBError err;
+ err.SetErrorToErrno();
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() ::ptrace "
+ "(PT_KILL, pid=%u, 0, 0) => 0x%8.8x (%s)",
+ m_pid, err.Error(), err.AsString());
+ m_thread_actions = DNBThreadResumeActions(eStateRunning, 0);
+ PrivateResume();
+
+ // Try and reap the process without touching our m_events since
+ // we want the code above this to still get the eStateExited event
+ const uint32_t reap_timeout_usec =
+ 1000000; // Wait 1 second and try to reap the process
+ const uint32_t reap_interval_usec = 10000; //
+ uint32_t reap_time_elapsed;
+ for (reap_time_elapsed = 0; reap_time_elapsed < reap_timeout_usec;
+ reap_time_elapsed += reap_interval_usec) {
+ if (GetState() == eStateExited)
+ break;
+ usleep(reap_interval_usec);
+ }
+ DNBLog("Waited %u ms for process to be reaped (state = %s)",
+ reap_time_elapsed / 1000, DNBStateAsString(GetState()));
+ return true;
+}
+
+bool MachProcess::Interrupt() {
+ nub_state_t state = GetState();
+ if (IsRunning(state)) {
+ if (m_sent_interrupt_signo == 0) {
+ m_sent_interrupt_signo = SIGSTOP;
+ if (Signal(m_sent_interrupt_signo)) {
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "MachProcess::Interrupt() - sent %i signal to interrupt process",
+ m_sent_interrupt_signo);
return true;
- }
- DNBLog("Resume() - task 0x%x has state %s, can't continue...", m_task.TaskPort(), DNBStateAsString(state));
- return false;
-}
-
-bool
-MachProcess::Kill (const struct timespec *timeout_abstime)
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill ()");
- nub_state_t state = DoSIGSTOP(true, false, NULL);
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() state = %s", DNBStateAsString(state));
- errno = 0;
- DNBLog ("Sending ptrace PT_KILL to terminate inferior process.");
- ::ptrace (PT_KILL, m_pid, 0, 0);
- DNBError err;
- err.SetErrorToErrno();
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() ::ptrace (PT_KILL, pid=%u, 0, 0) => 0x%8.8x (%s)", m_pid, err.Error(), err.AsString());
- m_thread_actions = DNBThreadResumeActions (eStateRunning, 0);
- PrivateResume ();
-
- // Try and reap the process without touching our m_events since
- // we want the code above this to still get the eStateExited event
- const uint32_t reap_timeout_usec = 1000000; // Wait 1 second and try to reap the process
- const uint32_t reap_interval_usec = 10000; //
- uint32_t reap_time_elapsed;
- for (reap_time_elapsed = 0;
- reap_time_elapsed < reap_timeout_usec;
- reap_time_elapsed += reap_interval_usec)
- {
- if (GetState() == eStateExited)
- break;
- usleep(reap_interval_usec);
- }
- DNBLog ("Waited %u ms for process to be reaped (state = %s)", reap_time_elapsed/1000, DNBStateAsString(GetState()));
+ } else {
+ m_sent_interrupt_signo = 0;
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - failed to "
+ "send %i signal to interrupt process",
+ m_sent_interrupt_signo);
+ }
+ } else {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - previously "
+ "sent an interrupt signal %i that hasn't "
+ "been received yet, interrupt aborted",
+ m_sent_interrupt_signo);
+ }
+ } else {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - process already "
+ "stopped, no interrupt sent");
+ }
+ return false;
+}
+
+bool MachProcess::Signal(int signal, const struct timespec *timeout_abstime) {
+ DNBLogThreadedIf(LOG_PROCESS,
+ "MachProcess::Signal (signal = %d, timeout = %p)", signal,
+ timeout_abstime);
+ nub_state_t state = GetState();
+ if (::kill(ProcessID(), signal) == 0) {
+ // If we were running and we have a timeout, wait for the signal to stop
+ if (IsRunning(state) && timeout_abstime) {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout "
+ "= %p) waiting for signal to stop "
+ "process...",
+ signal, timeout_abstime);
+ m_private_events.WaitForSetEvents(eEventProcessStoppedStateChanged,
+ timeout_abstime);
+ state = GetState();
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "MachProcess::Signal (signal = %d, timeout = %p) state = %s", signal,
+ timeout_abstime, DNBStateAsString(state));
+ return !IsRunning(state);
+ }
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "MachProcess::Signal (signal = %d, timeout = %p) not waiting...",
+ signal, timeout_abstime);
return true;
+ }
+ DNBError err(errno, DNBError::POSIX);
+ err.LogThreadedIfError("kill (pid = %d, signo = %i)", ProcessID(), signal);
+ return false;
}
-bool
-MachProcess::Interrupt()
-{
- nub_state_t state = GetState();
- if (IsRunning(state))
- {
- if (m_sent_interrupt_signo == 0)
- {
- m_sent_interrupt_signo = SIGSTOP;
- if (Signal (m_sent_interrupt_signo))
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - sent %i signal to interrupt process", m_sent_interrupt_signo);
- return true;
- }
- else
- {
- m_sent_interrupt_signo = 0;
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - failed to send %i signal to interrupt process", m_sent_interrupt_signo);
- }
- }
- else
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - previously sent an interrupt signal %i that hasn't been received yet, interrupt aborted", m_sent_interrupt_signo);
- }
- }
- else
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - process already stopped, no interrupt sent");
- }
- return false;
-}
-
-bool
-MachProcess::Signal (int signal, const struct timespec *timeout_abstime)
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout = %p)", signal, timeout_abstime);
- nub_state_t state = GetState();
- if (::kill (ProcessID(), signal) == 0)
- {
- // If we were running and we have a timeout, wait for the signal to stop
- if (IsRunning(state) && timeout_abstime)
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout = %p) waiting for signal to stop process...", signal, timeout_abstime);
- m_private_events.WaitForSetEvents(eEventProcessStoppedStateChanged, timeout_abstime);
- state = GetState();
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout = %p) state = %s", signal, timeout_abstime, DNBStateAsString(state));
- return !IsRunning (state);
- }
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout = %p) not waiting...", signal, timeout_abstime);
- return true;
- }
- DNBError err(errno, DNBError::POSIX);
- err.LogThreadedIfError("kill (pid = %d, signo = %i)", ProcessID(), signal);
+bool MachProcess::SendEvent(const char *event, DNBError &send_err) {
+ DNBLogThreadedIf(LOG_PROCESS,
+ "MachProcess::SendEvent (event = %s) to pid: %d", event,
+ m_pid);
+ if (m_pid == INVALID_NUB_PROCESS)
return false;
-
-}
-
-bool
-MachProcess::SendEvent (const char *event, DNBError &send_err)
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SendEvent (event = %s) to pid: %d", event, m_pid);
- if (m_pid == INVALID_NUB_PROCESS)
- return false;
- // FIXME: Shouldn't we use the launch flavor we were started with?
+// FIXME: Shouldn't we use the launch flavor we were started with?
#if defined(WITH_FBS) || defined(WITH_BKS)
- return BoardServiceSendEvent (event, send_err);
+ return BoardServiceSendEvent(event, send_err);
#endif
- return true;
+ return true;
}
-nub_state_t
-MachProcess::DoSIGSTOP (bool clear_bps_and_wps, bool allow_running, uint32_t *thread_idx_ptr)
-{
- nub_state_t state = GetState();
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s", DNBStateAsString (state));
-
- if (!IsRunning(state))
- {
- if (clear_bps_and_wps)
- {
- DisableAllBreakpoints (true);
- DisableAllWatchpoints (true);
- clear_bps_and_wps = false;
- }
+nub_state_t MachProcess::DoSIGSTOP(bool clear_bps_and_wps, bool allow_running,
+ uint32_t *thread_idx_ptr) {
+ nub_state_t state = GetState();
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s",
+ DNBStateAsString(state));
- // If we already have a thread stopped due to a SIGSTOP, we don't have
- // to do anything...
- uint32_t thread_idx = m_thread_list.GetThreadIndexForThreadStoppedWithSignal (SIGSTOP);
- if (thread_idx_ptr)
- *thread_idx_ptr = thread_idx;
- if (thread_idx != UINT32_MAX)
- return GetState();
-
- // No threads were stopped with a SIGSTOP, we need to run and halt the
- // process with a signal
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s -- resuming process", DNBStateAsString (state));
- if (allow_running)
- m_thread_actions = DNBThreadResumeActions (eStateRunning, 0);
- else
- m_thread_actions = DNBThreadResumeActions (eStateSuspended, 0);
-
- PrivateResume ();
-
- // Reset the event that says we were indeed running
- m_events.ResetEvents(eEventProcessRunningStateChanged);
- state = GetState();
- }
-
- // We need to be stopped in order to be able to detach, so we need
- // to send ourselves a SIGSTOP
-
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s -- sending SIGSTOP", DNBStateAsString (state));
- struct timespec sigstop_timeout;
- DNBTimer::OffsetTimeOfDay(&sigstop_timeout, 2, 0);
- Signal (SIGSTOP, &sigstop_timeout);
- if (clear_bps_and_wps)
- {
- DisableAllBreakpoints (true);
- DisableAllWatchpoints (true);
- //clear_bps_and_wps = false;
+ if (!IsRunning(state)) {
+ if (clear_bps_and_wps) {
+ DisableAllBreakpoints(true);
+ DisableAllWatchpoints(true);
+ clear_bps_and_wps = false;
}
- uint32_t thread_idx = m_thread_list.GetThreadIndexForThreadStoppedWithSignal (SIGSTOP);
+
+ // If we already have a thread stopped due to a SIGSTOP, we don't have
+ // to do anything...
+ uint32_t thread_idx =
+ m_thread_list.GetThreadIndexForThreadStoppedWithSignal(SIGSTOP);
if (thread_idx_ptr)
- *thread_idx_ptr = thread_idx;
- return GetState();
-}
+ *thread_idx_ptr = thread_idx;
+ if (thread_idx != UINT32_MAX)
+ return GetState();
+
+ // No threads were stopped with a SIGSTOP, we need to run and halt the
+ // process with a signal
+ DNBLogThreadedIf(LOG_PROCESS,
+ "MachProcess::DoSIGSTOP() state = %s -- resuming process",
+ DNBStateAsString(state));
+ if (allow_running)
+ m_thread_actions = DNBThreadResumeActions(eStateRunning, 0);
+ else
+ m_thread_actions = DNBThreadResumeActions(eStateSuspended, 0);
+
+ PrivateResume();
+
+ // Reset the event that says we were indeed running
+ m_events.ResetEvents(eEventProcessRunningStateChanged);
+ state = GetState();
+ }
+
+ // We need to be stopped in order to be able to detach, so we need
+ // to send ourselves a SIGSTOP
+
+ DNBLogThreadedIf(LOG_PROCESS,
+ "MachProcess::DoSIGSTOP() state = %s -- sending SIGSTOP",
+ DNBStateAsString(state));
+ struct timespec sigstop_timeout;
+ DNBTimer::OffsetTimeOfDay(&sigstop_timeout, 2, 0);
+ Signal(SIGSTOP, &sigstop_timeout);
+ if (clear_bps_and_wps) {
+ DisableAllBreakpoints(true);
+ DisableAllWatchpoints(true);
+ // clear_bps_and_wps = false;
+ }
+ uint32_t thread_idx =
+ m_thread_list.GetThreadIndexForThreadStoppedWithSignal(SIGSTOP);
+ if (thread_idx_ptr)
+ *thread_idx_ptr = thread_idx;
+ return GetState();
+}
+
+bool MachProcess::Detach() {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach()");
+
+ uint32_t thread_idx = UINT32_MAX;
+ nub_state_t state = DoSIGSTOP(true, true, &thread_idx);
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach() DoSIGSTOP() returned %s",
+ DNBStateAsString(state));
-bool
-MachProcess::Detach()
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach()");
+ {
+ m_thread_actions.Clear();
+ m_activities.Clear();
+ DNBThreadResumeAction thread_action;
+ thread_action.tid = m_thread_list.ThreadIDAtIndex(thread_idx);
+ thread_action.state = eStateRunning;
+ thread_action.signal = -1;
+ thread_action.addr = INVALID_NUB_ADDRESS;
- uint32_t thread_idx = UINT32_MAX;
- nub_state_t state = DoSIGSTOP(true, true, &thread_idx);
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach() DoSIGSTOP() returned %s", DNBStateAsString(state));
+ m_thread_actions.Append(thread_action);
+ m_thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
- {
- m_thread_actions.Clear();
- m_activities.Clear();
- DNBThreadResumeAction thread_action;
- thread_action.tid = m_thread_list.ThreadIDAtIndex (thread_idx);
- thread_action.state = eStateRunning;
- thread_action.signal = -1;
- thread_action.addr = INVALID_NUB_ADDRESS;
-
- m_thread_actions.Append (thread_action);
- m_thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
-
- PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex);
+ PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
- ReplyToAllExceptions ();
+ ReplyToAllExceptions();
+ }
- }
+ m_task.ShutDownExcecptionThread();
- m_task.ShutDownExcecptionThread();
+ // Detach from our process
+ errno = 0;
+ nub_process_t pid = m_pid;
+ int ret = ::ptrace(PT_DETACH, pid, (caddr_t)1, 0);
+ DNBError err(errno, DNBError::POSIX);
+ if (DNBLogCheckLogBit(LOG_PROCESS) || err.Fail() || (ret != 0))
+ err.LogThreaded("::ptrace (PT_DETACH, %u, (caddr_t)1, 0)", pid);
- // Detach from our process
- errno = 0;
- nub_process_t pid = m_pid;
- int ret = ::ptrace (PT_DETACH, pid, (caddr_t)1, 0);
- DNBError err(errno, DNBError::POSIX);
- if (DNBLogCheckLogBit(LOG_PROCESS) || err.Fail() || (ret != 0))
- err.LogThreaded("::ptrace (PT_DETACH, %u, (caddr_t)1, 0)", pid);
-
- // Resume our task
- m_task.Resume();
-
- // NULL our task out as we have already retored all exception ports
- m_task.Clear();
-
- // Clear out any notion of the process we once were
- const bool detaching = true;
- Clear(detaching);
+ // Resume our task
+ m_task.Resume();
- SetState(eStateDetached);
+ // NULL our task out as we have already retored all exception ports
+ m_task.Clear();
- return true;
+ // Clear out any notion of the process we once were
+ const bool detaching = true;
+ Clear(detaching);
+
+ SetState(eStateDetached);
+
+ return true;
}
//----------------------------------------------------------------------
@@ -1438,20 +1428,19 @@ MachProcess::Detach()
// (m_task.ReadMemory()) as that version will give you what is actually
// in inferior memory.
//----------------------------------------------------------------------
-nub_size_t
-MachProcess::ReadMemory (nub_addr_t addr, nub_size_t size, void *buf)
-{
- // We need to remove any current software traps (enabled software
- // breakpoints) that we may have placed in our tasks memory.
-
- // First just read the memory as is
- nub_size_t bytes_read = m_task.ReadMemory(addr, size, buf);
-
- // Then place any opcodes that fall into this range back into the buffer
- // before we return this to callers.
- if (bytes_read > 0)
- m_breakpoints.RemoveTrapsFromBuffer (addr, bytes_read, buf);
- return bytes_read;
+nub_size_t MachProcess::ReadMemory(nub_addr_t addr, nub_size_t size,
+ void *buf) {
+ // We need to remove any current software traps (enabled software
+ // breakpoints) that we may have placed in our tasks memory.
+
+ // First just read the memory as is
+ nub_size_t bytes_read = m_task.ReadMemory(addr, size, buf);
+
+ // Then place any opcodes that fall into this range back into the buffer
+ // before we return this to callers.
+ if (bytes_read > 0)
+ m_breakpoints.RemoveTrapsFromBuffer(addr, bytes_read, buf);
+ return bytes_read;
}
//----------------------------------------------------------------------
@@ -1463,1288 +1452,1275 @@ MachProcess::ReadMemory (nub_addr_t addr
// (m_task.WriteMemory()) as that version will always modify inferior
// memory.
//----------------------------------------------------------------------
-nub_size_t
-MachProcess::WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf)
-{
- // We need to write any data that would go where any current software traps
- // (enabled software breakpoints) any software traps (breakpoints) that we
- // may have placed in our tasks memory.
-
- std::vector<DNBBreakpoint *> bps;
-
- const size_t num_bps = m_breakpoints.FindBreakpointsThatOverlapRange(addr, size, bps);
- if (num_bps == 0)
- return m_task.WriteMemory(addr, size, buf);
-
- nub_size_t bytes_written = 0;
- nub_addr_t intersect_addr;
- nub_size_t intersect_size;
- nub_size_t opcode_offset;
- const uint8_t *ubuf = (const uint8_t *)buf;
-
- for (size_t i=0; i<num_bps; ++i)
- {
- DNBBreakpoint *bp = bps[i];
-
- const bool intersects = bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset);
- UNUSED_IF_ASSERT_DISABLED(intersects);
- assert(intersects);
- assert(addr <= intersect_addr && intersect_addr < addr + size);
- assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size);
- assert(opcode_offset + intersect_size <= bp->ByteSize());
-
- // Check for bytes before this breakpoint
- const nub_addr_t curr_addr = addr + bytes_written;
- if (intersect_addr > curr_addr)
- {
- // There are some bytes before this breakpoint that we need to
- // just write to memory
- nub_size_t curr_size = intersect_addr - curr_addr;
- nub_size_t curr_bytes_written = m_task.WriteMemory(curr_addr, curr_size, ubuf + bytes_written);
- bytes_written += curr_bytes_written;
- if (curr_bytes_written != curr_size)
- {
- // We weren't able to write all of the requested bytes, we
- // are done looping and will return the number of bytes that
- // we have written so far.
- break;
- }
- }
-
- // Now write any bytes that would cover up any software breakpoints
- // directly into the breakpoint opcode buffer
- ::memcpy(bp->SavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, intersect_size);
- bytes_written += intersect_size;
- }
-
- // Write any remaining bytes after the last breakpoint if we have any left
- if (bytes_written < size)
- bytes_written += m_task.WriteMemory(addr + bytes_written, size - bytes_written, ubuf + bytes_written);
-
- return bytes_written;
-}
-
-void
-MachProcess::ReplyToAllExceptions ()
-{
- PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
- if (m_exception_messages.empty() == false)
- {
- MachException::Message::iterator pos;
- MachException::Message::iterator begin = m_exception_messages.begin();
- MachException::Message::iterator end = m_exception_messages.end();
- for (pos = begin; pos != end; ++pos)
- {
- DNBLogThreadedIf(LOG_EXCEPTIONS, "Replying to exception %u...", (uint32_t)std::distance(begin, pos));
- int thread_reply_signal = 0;
-
- nub_thread_t tid = m_thread_list.GetThreadIDByMachPortNumber (pos->state.thread_port);
- const DNBThreadResumeAction *action = NULL;
- if (tid != INVALID_NUB_THREAD)
- {
- action = m_thread_actions.GetActionForThread (tid, false);
- }
+nub_size_t MachProcess::WriteMemory(nub_addr_t addr, nub_size_t size,
+ const void *buf) {
+ // We need to write any data that would go where any current software traps
+ // (enabled software breakpoints) any software traps (breakpoints) that we
+ // may have placed in our tasks memory.
+
+ std::vector<DNBBreakpoint *> bps;
+
+ const size_t num_bps =
+ m_breakpoints.FindBreakpointsThatOverlapRange(addr, size, bps);
+ if (num_bps == 0)
+ return m_task.WriteMemory(addr, size, buf);
+
+ nub_size_t bytes_written = 0;
+ nub_addr_t intersect_addr;
+ nub_size_t intersect_size;
+ nub_size_t opcode_offset;
+ const uint8_t *ubuf = (const uint8_t *)buf;
+
+ for (size_t i = 0; i < num_bps; ++i) {
+ DNBBreakpoint *bp = bps[i];
+
+ const bool intersects = bp->IntersectsRange(
+ addr, size, &intersect_addr, &intersect_size, &opcode_offset);
+ UNUSED_IF_ASSERT_DISABLED(intersects);
+ assert(intersects);
+ assert(addr <= intersect_addr && intersect_addr < addr + size);
+ assert(addr < intersect_addr + intersect_size &&
+ intersect_addr + intersect_size <= addr + size);
+ assert(opcode_offset + intersect_size <= bp->ByteSize());
+
+ // Check for bytes before this breakpoint
+ const nub_addr_t curr_addr = addr + bytes_written;
+ if (intersect_addr > curr_addr) {
+ // There are some bytes before this breakpoint that we need to
+ // just write to memory
+ nub_size_t curr_size = intersect_addr - curr_addr;
+ nub_size_t curr_bytes_written =
+ m_task.WriteMemory(curr_addr, curr_size, ubuf + bytes_written);
+ bytes_written += curr_bytes_written;
+ if (curr_bytes_written != curr_size) {
+ // We weren't able to write all of the requested bytes, we
+ // are done looping and will return the number of bytes that
+ // we have written so far.
+ break;
+ }
+ }
- if (action)
- {
- thread_reply_signal = action->signal;
- if (thread_reply_signal)
- m_thread_actions.SetSignalHandledForThread (tid);
- }
+ // Now write any bytes that would cover up any software breakpoints
+ // directly into the breakpoint opcode buffer
+ ::memcpy(bp->SavedOpcodeBytes() + opcode_offset, ubuf + bytes_written,
+ intersect_size);
+ bytes_written += intersect_size;
+ }
+
+ // Write any remaining bytes after the last breakpoint if we have any left
+ if (bytes_written < size)
+ bytes_written += m_task.WriteMemory(
+ addr + bytes_written, size - bytes_written, ubuf + bytes_written);
+
+ return bytes_written;
+}
+
+void MachProcess::ReplyToAllExceptions() {
+ PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
+ if (m_exception_messages.empty() == false) {
+ MachException::Message::iterator pos;
+ MachException::Message::iterator begin = m_exception_messages.begin();
+ MachException::Message::iterator end = m_exception_messages.end();
+ for (pos = begin; pos != end; ++pos) {
+ DNBLogThreadedIf(LOG_EXCEPTIONS, "Replying to exception %u...",
+ (uint32_t)std::distance(begin, pos));
+ int thread_reply_signal = 0;
+
+ nub_thread_t tid =
+ m_thread_list.GetThreadIDByMachPortNumber(pos->state.thread_port);
+ const DNBThreadResumeAction *action = NULL;
+ if (tid != INVALID_NUB_THREAD) {
+ action = m_thread_actions.GetActionForThread(tid, false);
+ }
+
+ if (action) {
+ thread_reply_signal = action->signal;
+ if (thread_reply_signal)
+ m_thread_actions.SetSignalHandledForThread(tid);
+ }
+
+ DNBError err(pos->Reply(this, thread_reply_signal));
+ if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
+ err.LogThreadedIfError("Error replying to exception");
+ }
+
+ // Erase all exception message as we should have used and replied
+ // to them all already.
+ m_exception_messages.clear();
+ }
+}
+void MachProcess::PrivateResume() {
+ PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
+
+ m_auto_resume_signo = m_sent_interrupt_signo;
+ if (m_auto_resume_signo)
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::PrivateResume() - task 0x%x "
+ "resuming (with unhandled interrupt signal "
+ "%i)...",
+ m_task.TaskPort(), m_auto_resume_signo);
+ else
+ DNBLogThreadedIf(LOG_PROCESS,
+ "MachProcess::PrivateResume() - task 0x%x resuming...",
+ m_task.TaskPort());
- DNBError err (pos->Reply(this, thread_reply_signal));
- if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
- err.LogThreadedIfError("Error replying to exception");
- }
+ ReplyToAllExceptions();
+ // bool stepOverBreakInstruction = step;
- // Erase all exception message as we should have used and replied
- // to them all already.
- m_exception_messages.clear();
- }
+ // Let the thread prepare to resume and see if any threads want us to
+ // step over a breakpoint instruction (ProcessWillResume will modify
+ // the value of stepOverBreakInstruction).
+ m_thread_list.ProcessWillResume(this, m_thread_actions);
+
+ // Set our state accordingly
+ if (m_thread_actions.NumActionsWithState(eStateStepping))
+ SetState(eStateStepping);
+ else
+ SetState(eStateRunning);
+
+ // Now resume our task.
+ m_task.Resume();
+}
+
+DNBBreakpoint *MachProcess::CreateBreakpoint(nub_addr_t addr, nub_size_t length,
+ bool hardware) {
+ DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = "
+ "0x%8.8llx, length = %llu, hardware = %i)",
+ (uint64_t)addr, (uint64_t)length, hardware);
+
+ DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr);
+ if (bp)
+ bp->Retain();
+ else
+ bp = m_breakpoints.Add(addr, length, hardware);
+
+ if (EnableBreakpoint(addr)) {
+ DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = "
+ "0x%8.8llx, length = %llu) => %p",
+ (uint64_t)addr, (uint64_t)length, bp);
+ return bp;
+ } else if (bp->Release() == 0) {
+ m_breakpoints.Remove(addr);
+ }
+ // We failed to enable the breakpoint
+ return NULL;
}
-void
-MachProcess::PrivateResume ()
-{
- PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex);
-
- m_auto_resume_signo = m_sent_interrupt_signo;
- if (m_auto_resume_signo)
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::PrivateResume() - task 0x%x resuming (with unhandled interrupt signal %i)...", m_task.TaskPort(), m_auto_resume_signo);
- else
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::PrivateResume() - task 0x%x resuming...", m_task.TaskPort());
-
- ReplyToAllExceptions ();
-// bool stepOverBreakInstruction = step;
-
- // Let the thread prepare to resume and see if any threads want us to
- // step over a breakpoint instruction (ProcessWillResume will modify
- // the value of stepOverBreakInstruction).
- m_thread_list.ProcessWillResume (this, m_thread_actions);
-
- // Set our state accordingly
- if (m_thread_actions.NumActionsWithState(eStateStepping))
- SetState (eStateStepping);
- else
- SetState (eStateRunning);
- // Now resume our task.
- m_task.Resume();
+DNBBreakpoint *MachProcess::CreateWatchpoint(nub_addr_t addr, nub_size_t length,
+ uint32_t watch_flags,
+ bool hardware) {
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = "
+ "0x%8.8llx, length = %llu, flags = "
+ "0x%8.8x, hardware = %i)",
+ (uint64_t)addr, (uint64_t)length, watch_flags, hardware);
+
+ DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr);
+ // since the Z packets only send an address, we can only have one watchpoint
+ // at
+ // an address. If there is already one, we must refuse to create another
+ // watchpoint
+ if (wp)
+ return NULL;
+
+ wp = m_watchpoints.Add(addr, length, hardware);
+ wp->SetIsWatchpoint(watch_flags);
+
+ if (EnableWatchpoint(addr)) {
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = "
+ "0x%8.8llx, length = %llu) => %p",
+ (uint64_t)addr, (uint64_t)length, wp);
+ return wp;
+ } else {
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = "
+ "0x%8.8llx, length = %llu) => FAILED",
+ (uint64_t)addr, (uint64_t)length);
+ m_watchpoints.Remove(addr);
+ }
+ // We failed to enable the watchpoint
+ return NULL;
}
-DNBBreakpoint *
-MachProcess::CreateBreakpoint(nub_addr_t addr, nub_size_t length, bool hardware)
-{
- DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = 0x%8.8llx, length = %llu, hardware = %i)", (uint64_t)addr, (uint64_t)length, hardware);
+void MachProcess::DisableAllBreakpoints(bool remove) {
+ DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::%s (remove = %d )",
+ __FUNCTION__, remove);
- DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr);
- if (bp)
- bp->Retain();
- else
- bp = m_breakpoints.Add(addr, length, hardware);
+ m_breakpoints.DisableAllBreakpoints(this);
- if (EnableBreakpoint(addr))
- {
- DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = 0x%8.8llx, length = %llu) => %p", (uint64_t)addr, (uint64_t)length, bp);
- return bp;
- }
- else if (bp->Release() == 0)
- {
- m_breakpoints.Remove(addr);
- }
- // We failed to enable the breakpoint
- return NULL;
+ if (remove)
+ m_breakpoints.RemoveDisabled();
}
-DNBBreakpoint *
-MachProcess::CreateWatchpoint(nub_addr_t addr, nub_size_t length, uint32_t watch_flags, bool hardware)
-{
- DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu, flags = 0x%8.8x, hardware = %i)", (uint64_t)addr, (uint64_t)length, watch_flags, hardware);
-
- DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr);
- // since the Z packets only send an address, we can only have one watchpoint at
- // an address. If there is already one, we must refuse to create another watchpoint
- if (wp)
- return NULL;
-
- wp = m_watchpoints.Add(addr, length, hardware);
- wp->SetIsWatchpoint(watch_flags);
-
- if (EnableWatchpoint(addr))
- {
- DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu) => %p", (uint64_t)addr, (uint64_t)length, wp);
- return wp;
- }
- else
- {
- DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu) => FAILED", (uint64_t)addr, (uint64_t)length);
- m_watchpoints.Remove(addr);
- }
- // We failed to enable the watchpoint
- return NULL;
-}
-
-void
-MachProcess::DisableAllBreakpoints (bool remove)
-{
- DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::%s (remove = %d )", __FUNCTION__, remove);
-
- m_breakpoints.DisableAllBreakpoints (this);
-
- if (remove)
- m_breakpoints.RemoveDisabled();
-}
-
-void
-MachProcess::DisableAllWatchpoints(bool remove)
-{
- DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::%s (remove = %d )", __FUNCTION__, remove);
-
- m_watchpoints.DisableAllWatchpoints(this);
-
- if (remove)
- m_watchpoints.RemoveDisabled();
-}
-
-bool
-MachProcess::DisableBreakpoint(nub_addr_t addr, bool remove)
-{
- DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr);
- if (bp)
- {
- // After "exec" we might end up with a bunch of breakpoints that were disabled
- // manually, just ignore them
- if (!bp->IsEnabled())
- {
- // Breakpoint might have been disabled by an exec
- if (remove && bp->Release() == 0)
- {
- m_thread_list.NotifyBreakpointChanged(bp);
- m_breakpoints.Remove(addr);
- }
- return true;
- }
-
- // We have multiple references to this breakpoint, decrement the ref count
- // and if it isn't zero, then return true;
- if (remove && bp->Release() > 0)
- return true;
-
- DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d )", (uint64_t)addr, remove);
-
- if (bp->IsHardware())
- {
- bool hw_disable_result = m_thread_list.DisableHardwareBreakpoint (bp);
-
- if (hw_disable_result == true)
- {
- bp->SetEnabled(false);
- // Let the thread list know that a breakpoint has been modified
- if (remove)
- {
- m_thread_list.NotifyBreakpointChanged(bp);
- m_breakpoints.Remove(addr);
- }
- DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) (hardware) => success", (uint64_t)addr, remove);
- return true;
- }
+void MachProcess::DisableAllWatchpoints(bool remove) {
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::%s (remove = %d )",
+ __FUNCTION__, remove);
- return false;
- }
+ m_watchpoints.DisableAllWatchpoints(this);
- const nub_size_t break_op_size = bp->ByteSize();
- assert (break_op_size > 0);
- const uint8_t * const break_op = DNBArchProtocol::GetBreakpointOpcode (bp->ByteSize());
- if (break_op_size > 0)
- {
- // Clear a software breakpoint instruction
- uint8_t curr_break_op[break_op_size];
- bool break_op_found = false;
-
- // Read the breakpoint opcode
- if (m_task.ReadMemory(addr, break_op_size, curr_break_op) == break_op_size)
- {
- bool verify = false;
- if (bp->IsEnabled())
- {
- // Make sure we have the a breakpoint opcode exists at this address
- if (memcmp(curr_break_op, break_op, break_op_size) == 0)
- {
- break_op_found = true;
- // We found a valid breakpoint opcode at this address, now restore
- // the saved opcode.
- if (m_task.WriteMemory(addr, break_op_size, bp->SavedOpcodeBytes()) == break_op_size)
- {
- verify = true;
- }
- else
- {
- DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) memory write failed when restoring original opcode", (uint64_t)addr, remove);
- }
- }
- else
- {
- DNBLogWarning("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) expected a breakpoint opcode but didn't find one.", (uint64_t)addr, remove);
- // Set verify to true and so we can check if the original opcode has already been restored
- verify = true;
- }
- }
- else
- {
- DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) is not enabled", (uint64_t)addr, remove);
- // Set verify to true and so we can check if the original opcode is there
- verify = true;
- }
-
- if (verify)
- {
- uint8_t verify_opcode[break_op_size];
- // Verify that our original opcode made it back to the inferior
- if (m_task.ReadMemory(addr, break_op_size, verify_opcode) == break_op_size)
- {
- // compare the memory we just read with the original opcode
- if (memcmp(bp->SavedOpcodeBytes(), verify_opcode, break_op_size) == 0)
- {
- // SUCCESS
- bp->SetEnabled(false);
- // Let the thread list know that a breakpoint has been modified
- if (remove && bp->Release() == 0)
- {
- m_thread_list.NotifyBreakpointChanged(bp);
- m_breakpoints.Remove(addr);
- }
- DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) => success", (uint64_t)addr, remove);
- return true;
- }
- else
- {
- if (break_op_found)
- DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) : failed to restore original opcode", (uint64_t)addr, remove);
- else
- DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) : opcode changed", (uint64_t)addr, remove);
- }
- }
- else
- {
- DNBLogWarning("MachProcess::DisableBreakpoint: unable to disable breakpoint 0x%8.8llx", (uint64_t)addr);
- }
- }
- }
- else
- {
- DNBLogWarning("MachProcess::DisableBreakpoint: unable to read memory at 0x%8.8llx", (uint64_t)addr);
- }
- }
- }
- else
- {
- DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) invalid breakpoint address", (uint64_t)addr, remove);
- }
- return false;
+ if (remove)
+ m_watchpoints.RemoveDisabled();
}
-bool
-MachProcess::DisableWatchpoint(nub_addr_t addr, bool remove)
-{
- DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::%s(addr = 0x%8.8llx, remove = %d)", __FUNCTION__, (uint64_t)addr, remove);
- DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr);
- if (wp)
- {
- // If we have multiple references to a watchpoint, removing the watchpoint shouldn't clear it
- if (remove && wp->Release() > 0)
- return true;
-
- nub_addr_t addr = wp->Address();
- DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = %d )", (uint64_t)addr, remove);
-
- if (wp->IsHardware())
- {
- bool hw_disable_result = m_thread_list.DisableHardwareWatchpoint (wp);
-
- if (hw_disable_result == true)
- {
- wp->SetEnabled(false);
- if (remove)
- m_watchpoints.Remove(addr);
- DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::Disablewatchpoint ( addr = 0x%8.8llx, remove = %d ) (hardware) => success", (uint64_t)addr, remove);
- return true;
- }
- }
-
- // TODO: clear software watchpoints if we implement them
- }
- else
- {
- DNBLogError("MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = %d ) invalid watchpoint ID", (uint64_t)addr, remove);
+bool MachProcess::DisableBreakpoint(nub_addr_t addr, bool remove) {
+ DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr);
+ if (bp) {
+ // After "exec" we might end up with a bunch of breakpoints that were
+ // disabled
+ // manually, just ignore them
+ if (!bp->IsEnabled()) {
+ // Breakpoint might have been disabled by an exec
+ if (remove && bp->Release() == 0) {
+ m_thread_list.NotifyBreakpointChanged(bp);
+ m_breakpoints.Remove(addr);
+ }
+ return true;
}
- return false;
-}
+ // We have multiple references to this breakpoint, decrement the ref count
+ // and if it isn't zero, then return true;
+ if (remove && bp->Release() > 0)
+ return true;
+
+ DNBLogThreadedIf(
+ LOG_BREAKPOINTS | LOG_VERBOSE,
+ "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d )",
+ (uint64_t)addr, remove);
+
+ if (bp->IsHardware()) {
+ bool hw_disable_result = m_thread_list.DisableHardwareBreakpoint(bp);
+
+ if (hw_disable_result == true) {
+ bp->SetEnabled(false);
+ // Let the thread list know that a breakpoint has been modified
+ if (remove) {
+ m_thread_list.NotifyBreakpointChanged(bp);
+ m_breakpoints.Remove(addr);
+ }
+ DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( "
+ "addr = 0x%8.8llx, remove = %d ) "
+ "(hardware) => success",
+ (uint64_t)addr, remove);
+ return true;
+ }
-uint32_t
-MachProcess::GetNumSupportedHardwareWatchpoints () const
-{
- return m_thread_list.NumSupportedHardwareWatchpoints();
-}
-
-bool
-MachProcess::EnableBreakpoint(nub_addr_t addr)
-{
- DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::EnableBreakpoint ( addr = 0x%8.8llx )", (uint64_t)addr);
- DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr);
- if (bp)
- {
- if (bp->IsEnabled())
- {
- DNBLogWarning("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): breakpoint already enabled.", (uint64_t)addr);
- return true;
- }
- else
- {
- if (bp->HardwarePreferred())
- {
- bp->SetHardwareIndex(m_thread_list.EnableHardwareBreakpoint(bp));
- if (bp->IsHardware())
- {
- bp->SetEnabled(true);
- return true;
- }
- }
+ return false;
+ }
- const nub_size_t break_op_size = bp->ByteSize();
- assert (break_op_size != 0);
- const uint8_t * const break_op = DNBArchProtocol::GetBreakpointOpcode (break_op_size);
- if (break_op_size > 0)
- {
- // Save the original opcode by reading it
- if (m_task.ReadMemory(addr, break_op_size, bp->SavedOpcodeBytes()) == break_op_size)
- {
- // Write a software breakpoint in place of the original opcode
- if (m_task.WriteMemory(addr, break_op_size, break_op) == break_op_size)
- {
- uint8_t verify_break_op[4];
- if (m_task.ReadMemory(addr, break_op_size, verify_break_op) == break_op_size)
- {
- if (memcmp(break_op, verify_break_op, break_op_size) == 0)
- {
- bp->SetEnabled(true);
- // Let the thread list know that a breakpoint has been modified
- m_thread_list.NotifyBreakpointChanged(bp);
- DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ) : SUCCESS.", (uint64_t)addr);
- return true;
- }
- else
- {
- DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): breakpoint opcode verification failed.", (uint64_t)addr);
- }
- }
- else
- {
- DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): unable to read memory to verify breakpoint opcode.", (uint64_t)addr);
- }
- }
- else
- {
- DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): unable to write breakpoint opcode to memory.", (uint64_t)addr);
- }
- }
- else
- {
- DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): unable to read memory at breakpoint address.", (uint64_t)addr);
- }
- }
- else
- {
- DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ) no software breakpoint opcode for current architecture.", (uint64_t)addr);
- }
- }
+ const nub_size_t break_op_size = bp->ByteSize();
+ assert(break_op_size > 0);
+ const uint8_t *const break_op =
+ DNBArchProtocol::GetBreakpointOpcode(bp->ByteSize());
+ if (break_op_size > 0) {
+ // Clear a software breakpoint instruction
+ uint8_t curr_break_op[break_op_size];
+ bool break_op_found = false;
+
+ // Read the breakpoint opcode
+ if (m_task.ReadMemory(addr, break_op_size, curr_break_op) ==
+ break_op_size) {
+ bool verify = false;
+ if (bp->IsEnabled()) {
+ // Make sure we have the a breakpoint opcode exists at this address
+ if (memcmp(curr_break_op, break_op, break_op_size) == 0) {
+ break_op_found = true;
+ // We found a valid breakpoint opcode at this address, now restore
+ // the saved opcode.
+ if (m_task.WriteMemory(addr, break_op_size,
+ bp->SavedOpcodeBytes()) == break_op_size) {
+ verify = true;
+ } else {
+ DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, "
+ "remove = %d ) memory write failed when restoring "
+ "original opcode",
+ (uint64_t)addr, remove);
+ }
+ } else {
+ DNBLogWarning("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, "
+ "remove = %d ) expected a breakpoint opcode but "
+ "didn't find one.",
+ (uint64_t)addr, remove);
+ // Set verify to true and so we can check if the original opcode has
+ // already been restored
+ verify = true;
+ }
+ } else {
+ DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE,
+ "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, "
+ "remove = %d ) is not enabled",
+ (uint64_t)addr, remove);
+ // Set verify to true and so we can check if the original opcode is
+ // there
+ verify = true;
+ }
+
+ if (verify) {
+ uint8_t verify_opcode[break_op_size];
+ // Verify that our original opcode made it back to the inferior
+ if (m_task.ReadMemory(addr, break_op_size, verify_opcode) ==
+ break_op_size) {
+ // compare the memory we just read with the original opcode
+ if (memcmp(bp->SavedOpcodeBytes(), verify_opcode, break_op_size) ==
+ 0) {
+ // SUCCESS
+ bp->SetEnabled(false);
+ // Let the thread list know that a breakpoint has been modified
+ if (remove && bp->Release() == 0) {
+ m_thread_list.NotifyBreakpointChanged(bp);
+ m_breakpoints.Remove(addr);
+ }
+ DNBLogThreadedIf(LOG_BREAKPOINTS,
+ "MachProcess::DisableBreakpoint ( addr = "
+ "0x%8.8llx, remove = %d ) => success",
+ (uint64_t)addr, remove);
+ return true;
+ } else {
+ if (break_op_found)
+ DNBLogError("MachProcess::DisableBreakpoint ( addr = "
+ "0x%8.8llx, remove = %d ) : failed to restore "
+ "original opcode",
+ (uint64_t)addr, remove);
+ else
+ DNBLogError("MachProcess::DisableBreakpoint ( addr = "
+ "0x%8.8llx, remove = %d ) : opcode changed",
+ (uint64_t)addr, remove);
+ }
+ } else {
+ DNBLogWarning("MachProcess::DisableBreakpoint: unable to disable "
+ "breakpoint 0x%8.8llx",
+ (uint64_t)addr);
+ }
+ }
+ } else {
+ DNBLogWarning("MachProcess::DisableBreakpoint: unable to read memory "
+ "at 0x%8.8llx",
+ (uint64_t)addr);
+ }
+ }
+ } else {
+ DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = "
+ "%d ) invalid breakpoint address",
+ (uint64_t)addr, remove);
+ }
+ return false;
+}
+
+bool MachProcess::DisableWatchpoint(nub_addr_t addr, bool remove) {
+ DNBLogThreadedIf(LOG_WATCHPOINTS,
+ "MachProcess::%s(addr = 0x%8.8llx, remove = %d)",
+ __FUNCTION__, (uint64_t)addr, remove);
+ DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr);
+ if (wp) {
+ // If we have multiple references to a watchpoint, removing the watchpoint
+ // shouldn't clear it
+ if (remove && wp->Release() > 0)
+ return true;
+
+ nub_addr_t addr = wp->Address();
+ DNBLogThreadedIf(
+ LOG_WATCHPOINTS,
+ "MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = %d )",
+ (uint64_t)addr, remove);
+
+ if (wp->IsHardware()) {
+ bool hw_disable_result = m_thread_list.DisableHardwareWatchpoint(wp);
+
+ if (hw_disable_result == true) {
+ wp->SetEnabled(false);
+ if (remove)
+ m_watchpoints.Remove(addr);
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::Disablewatchpoint ( "
+ "addr = 0x%8.8llx, remove = %d ) "
+ "(hardware) => success",
+ (uint64_t)addr, remove);
+ return true;
+ }
}
- return false;
-}
-bool
-MachProcess::EnableWatchpoint(nub_addr_t addr)
-{
- DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::EnableWatchpoint(addr = 0x%8.8llx)", (uint64_t)addr);
- DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr);
- if (wp)
- {
- nub_addr_t addr = wp->Address();
- if (wp->IsEnabled())
- {
- DNBLogWarning("MachProcess::EnableWatchpoint(addr = 0x%8.8llx): watchpoint already enabled.", (uint64_t)addr);
- return true;
- }
- else
- {
- // Currently only try and set hardware watchpoints.
- wp->SetHardwareIndex(m_thread_list.EnableHardwareWatchpoint(wp));
- if (wp->IsHardware())
- {
- wp->SetEnabled(true);
+ // TODO: clear software watchpoints if we implement them
+ } else {
+ DNBLogError("MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = "
+ "%d ) invalid watchpoint ID",
+ (uint64_t)addr, remove);
+ }
+ return false;
+}
+
+uint32_t MachProcess::GetNumSupportedHardwareWatchpoints() const {
+ return m_thread_list.NumSupportedHardwareWatchpoints();
+}
+
+bool MachProcess::EnableBreakpoint(nub_addr_t addr) {
+ DNBLogThreadedIf(LOG_BREAKPOINTS,
+ "MachProcess::EnableBreakpoint ( addr = 0x%8.8llx )",
+ (uint64_t)addr);
+ DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr);
+ if (bp) {
+ if (bp->IsEnabled()) {
+ DNBLogWarning("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): "
+ "breakpoint already enabled.",
+ (uint64_t)addr);
+ return true;
+ } else {
+ if (bp->HardwarePreferred()) {
+ bp->SetHardwareIndex(m_thread_list.EnableHardwareBreakpoint(bp));
+ if (bp->IsHardware()) {
+ bp->SetEnabled(true);
+ return true;
+ }
+ }
+
+ const nub_size_t break_op_size = bp->ByteSize();
+ assert(break_op_size != 0);
+ const uint8_t *const break_op =
+ DNBArchProtocol::GetBreakpointOpcode(break_op_size);
+ if (break_op_size > 0) {
+ // Save the original opcode by reading it
+ if (m_task.ReadMemory(addr, break_op_size, bp->SavedOpcodeBytes()) ==
+ break_op_size) {
+ // Write a software breakpoint in place of the original opcode
+ if (m_task.WriteMemory(addr, break_op_size, break_op) ==
+ break_op_size) {
+ uint8_t verify_break_op[4];
+ if (m_task.ReadMemory(addr, break_op_size, verify_break_op) ==
+ break_op_size) {
+ if (memcmp(break_op, verify_break_op, break_op_size) == 0) {
+ bp->SetEnabled(true);
+ // Let the thread list know that a breakpoint has been modified
+ m_thread_list.NotifyBreakpointChanged(bp);
+ DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::"
+ "EnableBreakpoint ( addr = "
+ "0x%8.8llx ) : SUCCESS.",
+ (uint64_t)addr);
return true;
- }
- // TODO: Add software watchpoints by doing page protection tricks.
- }
+ } else {
+ DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx "
+ "): breakpoint opcode verification failed.",
+ (uint64_t)addr);
+ }
+ } else {
+ DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): "
+ "unable to read memory to verify breakpoint opcode.",
+ (uint64_t)addr);
+ }
+ } else {
+ DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): "
+ "unable to write breakpoint opcode to memory.",
+ (uint64_t)addr);
+ }
+ } else {
+ DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): "
+ "unable to read memory at breakpoint address.",
+ (uint64_t)addr);
+ }
+ } else {
+ DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ) no "
+ "software breakpoint opcode for current architecture.",
+ (uint64_t)addr);
+ }
+ }
+ }
+ return false;
+}
+
+bool MachProcess::EnableWatchpoint(nub_addr_t addr) {
+ DNBLogThreadedIf(LOG_WATCHPOINTS,
+ "MachProcess::EnableWatchpoint(addr = 0x%8.8llx)",
+ (uint64_t)addr);
+ DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr);
+ if (wp) {
+ nub_addr_t addr = wp->Address();
+ if (wp->IsEnabled()) {
+ DNBLogWarning("MachProcess::EnableWatchpoint(addr = 0x%8.8llx): "
+ "watchpoint already enabled.",
+ (uint64_t)addr);
+ return true;
+ } else {
+ // Currently only try and set hardware watchpoints.
+ wp->SetHardwareIndex(m_thread_list.EnableHardwareWatchpoint(wp));
+ if (wp->IsHardware()) {
+ wp->SetEnabled(true);
+ return true;
+ }
+ // TODO: Add software watchpoints by doing page protection tricks.
}
- return false;
+ }
+ return false;
}
// Called by the exception thread when an exception has been received from
// our process. The exception message is completely filled and the exception
// data has already been copied.
-void
-MachProcess::ExceptionMessageReceived (const MachException::Message& exceptionMessage)
-{
- PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex);
-
- if (m_exception_messages.empty())
- m_task.Suspend();
-
- DNBLogThreadedIf(LOG_EXCEPTIONS, "MachProcess::ExceptionMessageReceived ( )");
-
- // Use a locker to automatically unlock our mutex in case of exceptions
- // Add the exception to our internal exception stack
- m_exception_messages.push_back(exceptionMessage);
-}
-
-task_t
-MachProcess::ExceptionMessageBundleComplete()
-{
- // We have a complete bundle of exceptions for our child process.
- PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex);
- DNBLogThreadedIf(LOG_EXCEPTIONS, "%s: %llu exception messages.", __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size());
- bool auto_resume = false;
- if (!m_exception_messages.empty())
- {
- m_did_exec = false;
- // First check for any SIGTRAP and make sure we didn't exec
- const task_t task = m_task.TaskPort();
- size_t i;
- if (m_pid != 0)
- {
- bool received_interrupt = false;
- uint32_t num_task_exceptions = 0;
- for (i=0; i<m_exception_messages.size(); ++i)
- {
- if (m_exception_messages[i].state.task_port == task)
- {
- ++num_task_exceptions;
- const int signo = m_exception_messages[i].state.SoftSignal();
- if (signo == SIGTRAP)
- {
- // SIGTRAP could mean that we exec'ed. We need to check the
- // dyld all_image_infos.infoArray to see if it is NULL and if
- // so, say that we exec'ed.
- const nub_addr_t aii_addr = GetDYLDAllImageInfosAddress();
- if (aii_addr != INVALID_NUB_ADDRESS)
- {
- const nub_addr_t info_array_count_addr = aii_addr + 4;
- uint32_t info_array_count = 0;
- if (m_task.ReadMemory(info_array_count_addr, 4, &info_array_count) == 4)
- {
- if (info_array_count == 0)
- {
- m_did_exec = true;
- // Force the task port to update itself in case the task port changed after exec
- DNBError err;
- const task_t old_task = m_task.TaskPort();
- const task_t new_task = m_task.TaskPortForProcessID (err, true);
- if (old_task != new_task)
- DNBLogThreadedIf(LOG_PROCESS, "exec: task changed from 0x%4.4x to 0x%4.4x", old_task, new_task);
- }
- }
- else
- {
- DNBLog ("error: failed to read all_image_infos.infoArrayCount from 0x%8.8llx", (uint64_t)info_array_count_addr);
- }
- }
- break;
- }
- else if (m_sent_interrupt_signo != 0 && signo == m_sent_interrupt_signo)
- {
- received_interrupt = true;
- }
- }
- }
-
- if (m_did_exec)
- {
- cpu_type_t process_cpu_type = MachProcess::GetCPUTypeForLocalProcess (m_pid);
- if (m_cpu_type != process_cpu_type)
- {
- DNBLog ("arch changed from 0x%8.8x to 0x%8.8x", m_cpu_type, process_cpu_type);
- m_cpu_type = process_cpu_type;
- DNBArchProtocol::SetArchitecture (process_cpu_type);
- }
- m_thread_list.Clear();
- m_activities.Clear();
- m_breakpoints.DisableAll();
- }
-
- if (m_sent_interrupt_signo != 0)
- {
- if (received_interrupt)
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::ExceptionMessageBundleComplete(): process successfully interrupted with signal %i", m_sent_interrupt_signo);
-
- // Mark that we received the interrupt signal
- m_sent_interrupt_signo = 0;
- // Not check if we had a case where:
- // 1 - We called MachProcess::Interrupt() but we stopped for another reason
- // 2 - We called MachProcess::Resume() (but still haven't gotten the interrupt signal)
- // 3 - We are now incorrectly stopped because we are handling the interrupt signal we missed
- // 4 - We might need to resume if we stopped only with the interrupt signal that we never handled
- if (m_auto_resume_signo != 0)
- {
- // Only auto_resume if we stopped with _only_ the interrupt signal
- if (num_task_exceptions == 1)
- {
- auto_resume = true;
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::ExceptionMessageBundleComplete(): auto resuming due to unhandled interrupt signal %i", m_auto_resume_signo);
- }
- m_auto_resume_signo = 0;
- }
- }
- else
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::ExceptionMessageBundleComplete(): didn't get signal %i after MachProcess::Interrupt()",
- m_sent_interrupt_signo);
+void MachProcess::ExceptionMessageReceived(
+ const MachException::Message &exceptionMessage) {
+ PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
+
+ if (m_exception_messages.empty())
+ m_task.Suspend();
+
+ DNBLogThreadedIf(LOG_EXCEPTIONS, "MachProcess::ExceptionMessageReceived ( )");
+
+ // Use a locker to automatically unlock our mutex in case of exceptions
+ // Add the exception to our internal exception stack
+ m_exception_messages.push_back(exceptionMessage);
+}
+
+task_t MachProcess::ExceptionMessageBundleComplete() {
+ // We have a complete bundle of exceptions for our child process.
+ PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
+ DNBLogThreadedIf(LOG_EXCEPTIONS, "%s: %llu exception messages.",
+ __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size());
+ bool auto_resume = false;
+ if (!m_exception_messages.empty()) {
+ m_did_exec = false;
+ // First check for any SIGTRAP and make sure we didn't exec
+ const task_t task = m_task.TaskPort();
+ size_t i;
+ if (m_pid != 0) {
+ bool received_interrupt = false;
+ uint32_t num_task_exceptions = 0;
+ for (i = 0; i < m_exception_messages.size(); ++i) {
+ if (m_exception_messages[i].state.task_port == task) {
+ ++num_task_exceptions;
+ const int signo = m_exception_messages[i].state.SoftSignal();
+ if (signo == SIGTRAP) {
+ // SIGTRAP could mean that we exec'ed. We need to check the
+ // dyld all_image_infos.infoArray to see if it is NULL and if
+ // so, say that we exec'ed.
+ const nub_addr_t aii_addr = GetDYLDAllImageInfosAddress();
+ if (aii_addr != INVALID_NUB_ADDRESS) {
+ const nub_addr_t info_array_count_addr = aii_addr + 4;
+ uint32_t info_array_count = 0;
+ if (m_task.ReadMemory(info_array_count_addr, 4,
+ &info_array_count) == 4) {
+ if (info_array_count == 0) {
+ m_did_exec = true;
+ // Force the task port to update itself in case the task port
+ // changed after exec
+ DNBError err;
+ const task_t old_task = m_task.TaskPort();
+ const task_t new_task =
+ m_task.TaskPortForProcessID(err, true);
+ if (old_task != new_task)
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "exec: task changed from 0x%4.4x to 0x%4.4x", old_task,
+ new_task);
}
+ } else {
+ DNBLog("error: failed to read all_image_infos.infoArrayCount "
+ "from 0x%8.8llx",
+ (uint64_t)info_array_count_addr);
+ }
}
+ break;
+ } else if (m_sent_interrupt_signo != 0 &&
+ signo == m_sent_interrupt_signo) {
+ received_interrupt = true;
+ }
+ }
+ }
+
+ if (m_did_exec) {
+ cpu_type_t process_cpu_type =
+ MachProcess::GetCPUTypeForLocalProcess(m_pid);
+ if (m_cpu_type != process_cpu_type) {
+ DNBLog("arch changed from 0x%8.8x to 0x%8.8x", m_cpu_type,
+ process_cpu_type);
+ m_cpu_type = process_cpu_type;
+ DNBArchProtocol::SetArchitecture(process_cpu_type);
}
-
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
- m_thread_list.ProcessDidStop(this);
+ m_thread_list.Clear();
m_activities.Clear();
+ m_breakpoints.DisableAll();
+ }
- // Let each thread know of any exceptions
- for (i=0; i<m_exception_messages.size(); ++i)
- {
- // Let the thread list figure use the MachProcess to forward all exceptions
- // on down to each thread.
- if (m_exception_messages[i].state.task_port == task)
- m_thread_list.NotifyException(m_exception_messages[i].state);
- if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
- m_exception_messages[i].Dump();
- }
-
- if (DNBLogCheckLogBit(LOG_THREAD))
- m_thread_list.Dump();
+ if (m_sent_interrupt_signo != 0) {
+ if (received_interrupt) {
+ DNBLogThreadedIf(LOG_PROCESS,
+ "MachProcess::ExceptionMessageBundleComplete(): "
+ "process successfully interrupted with signal %i",
+ m_sent_interrupt_signo);
+
+ // Mark that we received the interrupt signal
+ m_sent_interrupt_signo = 0;
+ // Not check if we had a case where:
+ // 1 - We called MachProcess::Interrupt() but we stopped for another
+ // reason
+ // 2 - We called MachProcess::Resume() (but still haven't gotten the
+ // interrupt signal)
+ // 3 - We are now incorrectly stopped because we are handling the
+ // interrupt signal we missed
+ // 4 - We might need to resume if we stopped only with the interrupt
+ // signal that we never handled
+ if (m_auto_resume_signo != 0) {
+ // Only auto_resume if we stopped with _only_ the interrupt signal
+ if (num_task_exceptions == 1) {
+ auto_resume = true;
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::"
+ "ExceptionMessageBundleComplete(): "
+ "auto resuming due to unhandled "
+ "interrupt signal %i",
+ m_auto_resume_signo);
+ }
+ m_auto_resume_signo = 0;
+ }
+ } else {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::"
+ "ExceptionMessageBundleComplete(): "
+ "didn't get signal %i after "
+ "MachProcess::Interrupt()",
+ m_sent_interrupt_signo);
+ }
+ }
+ }
+
+ // Let all threads recover from stopping and do any clean up based
+ // on the previous thread state (if any).
+ m_thread_list.ProcessDidStop(this);
+ m_activities.Clear();
- bool step_more = false;
- if (m_thread_list.ShouldStop(step_more) && auto_resume == false)
- {
- // Wait for the eEventProcessRunningStateChanged event to be reset
- // before changing state to stopped to avoid race condition with
- // very fast start/stops
- struct timespec timeout;
- //DNBTimer::OffsetTimeOfDay(&timeout, 0, 250 * 1000); // Wait for 250 ms
- DNBTimer::OffsetTimeOfDay(&timeout, 1, 0); // Wait for 250 ms
- m_events.WaitForEventsToReset(eEventProcessRunningStateChanged, &timeout);
- SetState(eStateStopped);
- }
- else
- {
- // Resume without checking our current state.
- PrivateResume ();
- }
- }
- else
- {
- DNBLogThreadedIf(LOG_EXCEPTIONS, "%s empty exception messages bundle (%llu exceptions).", __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size());
- }
- return m_task.TaskPort();
+ // Let each thread know of any exceptions
+ for (i = 0; i < m_exception_messages.size(); ++i) {
+ // Let the thread list figure use the MachProcess to forward all
+ // exceptions
+ // on down to each thread.
+ if (m_exception_messages[i].state.task_port == task)
+ m_thread_list.NotifyException(m_exception_messages[i].state);
+ if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
+ m_exception_messages[i].Dump();
+ }
+
+ if (DNBLogCheckLogBit(LOG_THREAD))
+ m_thread_list.Dump();
+
+ bool step_more = false;
+ if (m_thread_list.ShouldStop(step_more) && auto_resume == false) {
+ // Wait for the eEventProcessRunningStateChanged event to be reset
+ // before changing state to stopped to avoid race condition with
+ // very fast start/stops
+ struct timespec timeout;
+ // DNBTimer::OffsetTimeOfDay(&timeout, 0, 250 * 1000); // Wait for 250
+ // ms
+ DNBTimer::OffsetTimeOfDay(&timeout, 1, 0); // Wait for 250 ms
+ m_events.WaitForEventsToReset(eEventProcessRunningStateChanged, &timeout);
+ SetState(eStateStopped);
+ } else {
+ // Resume without checking our current state.
+ PrivateResume();
+ }
+ } else {
+ DNBLogThreadedIf(
+ LOG_EXCEPTIONS, "%s empty exception messages bundle (%llu exceptions).",
+ __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size());
+ }
+ return m_task.TaskPort();
}
nub_size_t
-MachProcess::CopyImageInfos ( struct DNBExecutableImageInfo **image_infos, bool only_changed)
-{
- if (m_image_infos_callback != NULL)
- return m_image_infos_callback(ProcessID(), image_infos, only_changed, m_image_infos_baton);
- return 0;
-}
+MachProcess::CopyImageInfos(struct DNBExecutableImageInfo **image_infos,
+ bool only_changed) {
+ if (m_image_infos_callback != NULL)
+ return m_image_infos_callback(ProcessID(), image_infos, only_changed,
+ m_image_infos_baton);
+ return 0;
+}
+
+void MachProcess::SharedLibrariesUpdated() {
+ uint32_t event_bits = eEventSharedLibsStateChange;
+ // Set the shared library event bit to let clients know of shared library
+ // changes
+ m_events.SetEvents(event_bits);
+ // Wait for the event bit to reset if a reset ACK is requested
+ m_events.WaitForResetAck(event_bits);
+}
+
+void MachProcess::SetExitInfo(const char *info) {
+ if (info && info[0]) {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s(\"%s\")", __FUNCTION__,
+ info);
+ m_exit_info.assign(info);
+ } else {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s(NULL)", __FUNCTION__);
+ m_exit_info.clear();
+ }
+}
+
+void MachProcess::AppendSTDOUT(char *s, size_t len) {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (<%llu> %s) ...", __FUNCTION__,
+ (uint64_t)len, s);
+ PTHREAD_MUTEX_LOCKER(locker, m_stdio_mutex);
+ m_stdout_data.append(s, len);
+ m_events.SetEvents(eEventStdioAvailable);
+
+ // Wait for the event bit to reset if a reset ACK is requested
+ m_events.WaitForResetAck(eEventStdioAvailable);
+}
+
+size_t MachProcess::GetAvailableSTDOUT(char *buf, size_t buf_size) {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (&%p[%llu]) ...", __FUNCTION__,
+ buf, (uint64_t)buf_size);
+ PTHREAD_MUTEX_LOCKER(locker, m_stdio_mutex);
+ size_t bytes_available = m_stdout_data.size();
+ if (bytes_available > 0) {
+ if (bytes_available > buf_size) {
+ memcpy(buf, m_stdout_data.data(), buf_size);
+ m_stdout_data.erase(0, buf_size);
+ bytes_available = buf_size;
+ } else {
+ memcpy(buf, m_stdout_data.data(), bytes_available);
+ m_stdout_data.clear();
+ }
+ }
+ return bytes_available;
+}
+
+nub_addr_t MachProcess::GetDYLDAllImageInfosAddress() {
+ DNBError err;
+ return m_task.GetDYLDAllImageInfosAddress(err);
+}
+
+size_t MachProcess::GetAvailableSTDERR(char *buf, size_t buf_size) { return 0; }
+
+void *MachProcess::STDIOThread(void *arg) {
+ MachProcess *proc = (MachProcess *)arg;
+ DNBLogThreadedIf(LOG_PROCESS,
+ "MachProcess::%s ( arg = %p ) thread starting...",
+ __FUNCTION__, arg);
+
+#if defined(__APPLE__)
+ pthread_setname_np("stdio monitoring thread");
+#endif
+
+ // We start use a base and more options so we can control if we
+ // are currently using a timeout on the mach_msg. We do this to get a
+ // bunch of related exceptions on our exception port so we can process
+ // then together. When we have multiple threads, we can get an exception
+ // per thread and they will come in consecutively. The main thread loop
+ // will start by calling mach_msg to without having the MACH_RCV_TIMEOUT
+ // flag set in the options, so we will wait forever for an exception on
+ // our exception port. After we get one exception, we then will use the
+ // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current
+ // exceptions for our process. After we have received the last pending
+ // exception, we will get a timeout which enables us to then notify
+ // our main thread that we have an exception bundle available. We then wait
+ // for the main thread to tell this exception thread to start trying to get
+ // exceptions messages again and we start again with a mach_msg read with
+ // infinite timeout.
+ DNBError err;
+ int stdout_fd = proc->GetStdoutFileDescriptor();
+ int stderr_fd = proc->GetStderrFileDescriptor();
+ if (stdout_fd == stderr_fd)
+ stderr_fd = -1;
+
+ while (stdout_fd >= 0 || stderr_fd >= 0) {
+ ::pthread_testcancel();
+
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+ if (stdout_fd >= 0)
+ FD_SET(stdout_fd, &read_fds);
+ if (stderr_fd >= 0)
+ FD_SET(stderr_fd, &read_fds);
+ int nfds = std::max<int>(stdout_fd, stderr_fd) + 1;
-void
-MachProcess::SharedLibrariesUpdated ( )
-{
- uint32_t event_bits = eEventSharedLibsStateChange;
- // Set the shared library event bit to let clients know of shared library
- // changes
- m_events.SetEvents(event_bits);
- // Wait for the event bit to reset if a reset ACK is requested
- m_events.WaitForResetAck(event_bits);
+ int num_set_fds = select(nfds, &read_fds, NULL, NULL, NULL);
+ DNBLogThreadedIf(LOG_PROCESS,
+ "select (nfds, &read_fds, NULL, NULL, NULL) => %d",
+ num_set_fds);
+
+ if (num_set_fds < 0) {
+ int select_errno = errno;
+ if (DNBLogCheckLogBit(LOG_PROCESS)) {
+ err.SetError(select_errno, DNBError::POSIX);
+ err.LogThreadedIfError(
+ "select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds);
+ }
+
+ switch (select_errno) {
+ case EAGAIN: // The kernel was (perhaps temporarily) unable to allocate
+ // the requested number of file descriptors, or we have
+ // non-blocking IO
+ break;
+ case EBADF: // One of the descriptor sets specified an invalid descriptor.
+ return NULL;
+ break;
+ case EINTR: // A signal was delivered before the time limit expired and
+ // before any of the selected events occurred.
+ case EINVAL: // The specified time limit is invalid. One of its components
+ // is negative or too large.
+ default: // Other unknown error
+ break;
+ }
+ } else if (num_set_fds == 0) {
+ } else {
+ char s[1024];
+ s[sizeof(s) - 1] = '\0'; // Ensure we have NULL termination
+ ssize_t bytes_read = 0;
+ if (stdout_fd >= 0 && FD_ISSET(stdout_fd, &read_fds)) {
+ do {
+ bytes_read = ::read(stdout_fd, s, sizeof(s) - 1);
+ if (bytes_read < 0) {
+ int read_errno = errno;
+ DNBLogThreadedIf(LOG_PROCESS,
+ "read (stdout_fd, ) => %zd errno: %d (%s)",
+ bytes_read, read_errno, strerror(read_errno));
+ } else if (bytes_read == 0) {
+ // EOF...
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "read (stdout_fd, ) => %zd (reached EOF for child STDOUT)",
+ bytes_read);
+ stdout_fd = -1;
+ } else if (bytes_read > 0) {
+ proc->AppendSTDOUT(s, bytes_read);
+ }
+
+ } while (bytes_read > 0);
+ }
+
+ if (stderr_fd >= 0 && FD_ISSET(stderr_fd, &read_fds)) {
+ do {
+ bytes_read = ::read(stderr_fd, s, sizeof(s) - 1);
+ if (bytes_read < 0) {
+ int read_errno = errno;
+ DNBLogThreadedIf(LOG_PROCESS,
+ "read (stderr_fd, ) => %zd errno: %d (%s)",
+ bytes_read, read_errno, strerror(read_errno));
+ } else if (bytes_read == 0) {
+ // EOF...
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "read (stderr_fd, ) => %zd (reached EOF for child STDERR)",
+ bytes_read);
+ stderr_fd = -1;
+ } else if (bytes_read > 0) {
+ proc->AppendSTDOUT(s, bytes_read);
+ }
+
+ } while (bytes_read > 0);
+ }
+ }
+ }
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (%p): thread exiting...",
+ __FUNCTION__, arg);
+ return NULL;
}
-void
-MachProcess::SetExitInfo (const char *info)
-{
- if (info && info[0])
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s(\"%s\")", __FUNCTION__, info);
- m_exit_info.assign(info);
- }
- else
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s(NULL)", __FUNCTION__);
- m_exit_info.clear();
- }
+void MachProcess::SignalAsyncProfileData(const char *info) {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (%s) ...", __FUNCTION__, info);
+ PTHREAD_MUTEX_LOCKER(locker, m_profile_data_mutex);
+ m_profile_data.push_back(info);
+ m_events.SetEvents(eEventProfileDataAvailable);
+
+ // Wait for the event bit to reset if a reset ACK is requested
+ m_events.WaitForResetAck(eEventProfileDataAvailable);
}
-void
-MachProcess::AppendSTDOUT (char* s, size_t len)
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (<%llu> %s) ...", __FUNCTION__, (uint64_t)len, s);
- PTHREAD_MUTEX_LOCKER (locker, m_stdio_mutex);
- m_stdout_data.append(s, len);
- m_events.SetEvents(eEventStdioAvailable);
+size_t MachProcess::GetAsyncProfileData(char *buf, size_t buf_size) {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (&%p[%llu]) ...", __FUNCTION__,
+ buf, (uint64_t)buf_size);
+ PTHREAD_MUTEX_LOCKER(locker, m_profile_data_mutex);
+ if (m_profile_data.empty())
+ return 0;
- // Wait for the event bit to reset if a reset ACK is requested
- m_events.WaitForResetAck(eEventStdioAvailable);
+ size_t bytes_available = m_profile_data.front().size();
+ if (bytes_available > 0) {
+ if (bytes_available > buf_size) {
+ memcpy(buf, m_profile_data.front().data(), buf_size);
+ m_profile_data.front().erase(0, buf_size);
+ bytes_available = buf_size;
+ } else {
+ memcpy(buf, m_profile_data.front().data(), bytes_available);
+ m_profile_data.erase(m_profile_data.begin());
+ }
+ }
+ return bytes_available;
+}
+
+void *MachProcess::ProfileThread(void *arg) {
+ MachProcess *proc = (MachProcess *)arg;
+ DNBLogThreadedIf(LOG_PROCESS,
+ "MachProcess::%s ( arg = %p ) thread starting...",
+ __FUNCTION__, arg);
+
+#if defined(__APPLE__)
+ pthread_setname_np("performance profiling thread");
+#endif
+
+ while (proc->IsProfilingEnabled()) {
+ nub_state_t state = proc->GetState();
+ if (state == eStateRunning) {
+ std::string data =
+ proc->Task().GetProfileData(proc->GetProfileScanType());
+ if (!data.empty()) {
+ proc->SignalAsyncProfileData(data.c_str());
+ }
+ } else if ((state == eStateUnloaded) || (state == eStateDetached) ||
+ (state == eStateUnloaded)) {
+ // Done. Get out of this thread.
+ break;
+ }
+
+ // A simple way to set up the profile interval. We can also use select() or
+ // dispatch timer source if necessary.
+ usleep(proc->ProfileInterval());
+ }
+ return NULL;
}
-size_t
-MachProcess::GetAvailableSTDOUT (char *buf, size_t buf_size)
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (&%p[%llu]) ...", __FUNCTION__, buf, (uint64_t)buf_size);
- PTHREAD_MUTEX_LOCKER (locker, m_stdio_mutex);
- size_t bytes_available = m_stdout_data.size();
- if (bytes_available > 0)
- {
- if (bytes_available > buf_size)
- {
- memcpy(buf, m_stdout_data.data(), buf_size);
- m_stdout_data.erase(0, buf_size);
- bytes_available = buf_size;
- }
- else
- {
- memcpy(buf, m_stdout_data.data(), bytes_available);
- m_stdout_data.clear();
- }
+pid_t MachProcess::AttachForDebug(pid_t pid, char *err_str, size_t err_len) {
+ // Clear out and clean up from any current state
+ Clear();
+ if (pid != 0) {
+ DNBError err;
+ // Make sure the process exists...
+ if (::getpgid(pid) < 0) {
+ err.SetErrorToErrno();
+ const char *err_cstr = err.AsString();
+ ::snprintf(err_str, err_len, "%s",
+ err_cstr ? err_cstr : "No such process");
+ return INVALID_NUB_PROCESS;
}
- return bytes_available;
-}
-nub_addr_t
-MachProcess::GetDYLDAllImageInfosAddress ()
-{
- DNBError err;
- return m_task.GetDYLDAllImageInfosAddress(err);
+ SetState(eStateAttaching);
+ m_pid = pid;
+// Let ourselves know we are going to be using SBS or BKS if the correct flag
+// bit is set...
+#if defined(WITH_FBS) || defined(WITH_BKS)
+ bool found_app_flavor = false;
+#endif
+
+#if defined(WITH_FBS)
+ if (!found_app_flavor && IsFBSProcess(pid)) {
+ found_app_flavor = true;
+ m_flags |= eMachProcessFlagsUsingFBS;
+ }
+#elif defined(WITH_BKS)
+ if (!found_app_flavor && IsBKSProcess(pid)) {
+ found_app_flavor = true;
+ m_flags |= eMachProcessFlagsUsingBKS;
+ }
+#elif defined(WITH_SPRINGBOARD)
+ if (IsSBProcess(pid))
+ m_flags |= eMachProcessFlagsUsingSBS;
+#endif
+ if (!m_task.StartExceptionThread(err)) {
+ const char *err_cstr = err.AsString();
+ ::snprintf(err_str, err_len, "%s",
+ err_cstr ? err_cstr : "unable to start the exception thread");
+ DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", pid);
+ m_pid = INVALID_NUB_PROCESS;
+ return INVALID_NUB_PROCESS;
+ }
+
+ errno = 0;
+ if (::ptrace(PT_ATTACHEXC, pid, 0, 0))
+ err.SetError(errno);
+ else
+ err.Clear();
+
+ if (err.Success()) {
+ m_flags |= eMachProcessFlagsAttached;
+ // Sleep a bit to let the exception get received and set our process
+ // status
+ // to stopped.
+ ::usleep(250000);
+ DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", pid);
+ return m_pid;
+ } else {
+ ::snprintf(err_str, err_len, "%s", err.AsString());
+ DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", pid);
+ }
+ }
+ return INVALID_NUB_PROCESS;
+}
+
+Genealogy::ThreadActivitySP
+MachProcess::GetGenealogyInfoForThread(nub_thread_t tid, bool &timed_out) {
+ return m_activities.GetGenealogyInfoForThread(m_pid, tid, m_thread_list,
+ m_task.TaskPort(), timed_out);
}
-size_t
-MachProcess::GetAvailableSTDERR (char *buf, size_t buf_size)
-{
- return 0;
+Genealogy::ProcessExecutableInfoSP
+MachProcess::GetGenealogyImageInfo(size_t idx) {
+ return m_activities.GetProcessExecutableInfosAtIndex(idx);
}
-void *
-MachProcess::STDIOThread(void *arg)
-{
- MachProcess *proc = (MachProcess*) arg;
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( arg = %p ) thread starting...", __FUNCTION__, arg);
-
-#if defined (__APPLE__)
- pthread_setname_np ("stdio monitoring thread");
-#endif
-
- // We start use a base and more options so we can control if we
- // are currently using a timeout on the mach_msg. We do this to get a
- // bunch of related exceptions on our exception port so we can process
- // then together. When we have multiple threads, we can get an exception
- // per thread and they will come in consecutively. The main thread loop
- // will start by calling mach_msg to without having the MACH_RCV_TIMEOUT
- // flag set in the options, so we will wait forever for an exception on
- // our exception port. After we get one exception, we then will use the
- // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current
- // exceptions for our process. After we have received the last pending
- // exception, we will get a timeout which enables us to then notify
- // our main thread that we have an exception bundle available. We then wait
- // for the main thread to tell this exception thread to start trying to get
- // exceptions messages again and we start again with a mach_msg read with
- // infinite timeout.
- DNBError err;
- int stdout_fd = proc->GetStdoutFileDescriptor();
- int stderr_fd = proc->GetStderrFileDescriptor();
- if (stdout_fd == stderr_fd)
- stderr_fd = -1;
-
- while (stdout_fd >= 0 || stderr_fd >= 0)
- {
- ::pthread_testcancel ();
-
- fd_set read_fds;
- FD_ZERO (&read_fds);
- if (stdout_fd >= 0)
- FD_SET (stdout_fd, &read_fds);
- if (stderr_fd >= 0)
- FD_SET (stderr_fd, &read_fds);
- int nfds = std::max<int>(stdout_fd, stderr_fd) + 1;
-
- int num_set_fds = select (nfds, &read_fds, NULL, NULL, NULL);
- DNBLogThreadedIf(LOG_PROCESS, "select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds);
-
- if (num_set_fds < 0)
- {
- int select_errno = errno;
- if (DNBLogCheckLogBit(LOG_PROCESS))
- {
- err.SetError (select_errno, DNBError::POSIX);
- err.LogThreadedIfError("select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds);
- }
+bool MachProcess::GetOSVersionNumbers(uint64_t *major, uint64_t *minor,
+ uint64_t *patch) {
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
+ (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000)
+ return false;
+#else
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- switch (select_errno)
- {
- case EAGAIN: // The kernel was (perhaps temporarily) unable to allocate the requested number of file descriptors, or we have non-blocking IO
- break;
- case EBADF: // One of the descriptor sets specified an invalid descriptor.
- return NULL;
- break;
- case EINTR: // A signal was delivered before the time limit expired and before any of the selected events occurred.
- case EINVAL: // The specified time limit is invalid. One of its components is negative or too large.
- default: // Other unknown error
- break;
- }
- }
- else if (num_set_fds == 0)
- {
- }
- else
- {
- char s[1024];
- s[sizeof(s)-1] = '\0'; // Ensure we have NULL termination
- ssize_t bytes_read = 0;
- if (stdout_fd >= 0 && FD_ISSET (stdout_fd, &read_fds))
- {
- do
- {
- bytes_read = ::read (stdout_fd, s, sizeof(s)-1);
- if (bytes_read < 0)
- {
- int read_errno = errno;
- DNBLogThreadedIf(LOG_PROCESS, "read (stdout_fd, ) => %zd errno: %d (%s)", bytes_read, read_errno, strerror(read_errno));
- }
- else if (bytes_read == 0)
- {
- // EOF...
- DNBLogThreadedIf(LOG_PROCESS, "read (stdout_fd, ) => %zd (reached EOF for child STDOUT)", bytes_read);
- stdout_fd = -1;
- }
- else if (bytes_read > 0)
- {
- proc->AppendSTDOUT(s, bytes_read);
- }
+ NSOperatingSystemVersion vers =
+ [[NSProcessInfo processInfo] operatingSystemVersion];
+ if (major)
+ *major = vers.majorVersion;
+ if (minor)
+ *minor = vers.minorVersion;
+ if (patch)
+ *patch = vers.patchVersion;
+
+ [pool drain];
+
+ return true;
+#endif
+}
- } while (bytes_read > 0);
- }
+// Do the process specific setup for attach. If this returns NULL, then there's
+// no
+// platform specific stuff to be done to wait for the attach. If you get
+// non-null,
+// pass that token to the CheckForProcess method, and then to
+// CleanupAfterAttach.
+
+// Call PrepareForAttach before attaching to a process that has not yet
+// launched
+// This returns a token that can be passed to CheckForProcess, and to
+// CleanupAfterAttach.
+// You should call CleanupAfterAttach to free the token, and do whatever other
+// cleanup seems good.
- if (stderr_fd >= 0 && FD_ISSET (stderr_fd, &read_fds))
- {
- do
- {
- bytes_read = ::read (stderr_fd, s, sizeof(s)-1);
- if (bytes_read < 0)
- {
- int read_errno = errno;
- DNBLogThreadedIf(LOG_PROCESS, "read (stderr_fd, ) => %zd errno: %d (%s)", bytes_read, read_errno, strerror(read_errno));
- }
- else if (bytes_read == 0)
- {
- // EOF...
- DNBLogThreadedIf(LOG_PROCESS, "read (stderr_fd, ) => %zd (reached EOF for child STDERR)", bytes_read);
- stderr_fd = -1;
- }
- else if (bytes_read > 0)
- {
- proc->AppendSTDOUT(s, bytes_read);
- }
+const void *MachProcess::PrepareForAttach(const char *path,
+ nub_launch_flavor_t launch_flavor,
+ bool waitfor, DNBError &attach_err) {
+#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) || defined(WITH_FBS)
+ // Tell SpringBoard to halt the next launch of this application on startup.
- } while (bytes_read > 0);
- }
- }
- }
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (%p): thread exiting...", __FUNCTION__, arg);
+ if (!waitfor)
return NULL;
-}
+ const char *app_ext = strstr(path, ".app");
+ const bool is_app =
+ app_ext != NULL && (app_ext[4] == '\0' || app_ext[4] == '/');
+ if (!is_app) {
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "MachProcess::PrepareForAttach(): path '%s' doesn't contain .app, "
+ "we can't tell springboard to wait for launch...",
+ path);
+ return NULL;
+ }
-void
-MachProcess::SignalAsyncProfileData (const char *info)
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (%s) ...", __FUNCTION__, info);
- PTHREAD_MUTEX_LOCKER (locker, m_profile_data_mutex);
- m_profile_data.push_back(info);
- m_events.SetEvents(eEventProfileDataAvailable);
-
- // Wait for the event bit to reset if a reset ACK is requested
- m_events.WaitForResetAck(eEventProfileDataAvailable);
-}
+#if defined(WITH_FBS)
+ if (launch_flavor == eLaunchFlavorDefault)
+ launch_flavor = eLaunchFlavorFBS;
+ if (launch_flavor != eLaunchFlavorFBS)
+ return NULL;
+#elif defined(WITH_BKS)
+ if (launch_flavor == eLaunchFlavorDefault)
+ launch_flavor = eLaunchFlavorBKS;
+ if (launch_flavor != eLaunchFlavorBKS)
+ return NULL;
+#elif defined(WITH_SPRINGBOARD)
+ if (launch_flavor == eLaunchFlavorDefault)
+ launch_flavor = eLaunchFlavorSpringBoard;
+ if (launch_flavor != eLaunchFlavorSpringBoard)
+ return NULL;
+#endif
+ std::string app_bundle_path(path, app_ext + strlen(".app"));
-size_t
-MachProcess::GetAsyncProfileData (char *buf, size_t buf_size)
-{
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (&%p[%llu]) ...", __FUNCTION__, buf, (uint64_t)buf_size);
- PTHREAD_MUTEX_LOCKER (locker, m_profile_data_mutex);
- if (m_profile_data.empty())
- return 0;
-
- size_t bytes_available = m_profile_data.front().size();
- if (bytes_available > 0)
- {
- if (bytes_available > buf_size)
- {
- memcpy(buf, m_profile_data.front().data(), buf_size);
- m_profile_data.front().erase(0, buf_size);
- bytes_available = buf_size;
- }
- else
- {
- memcpy(buf, m_profile_data.front().data(), bytes_available);
- m_profile_data.erase(m_profile_data.begin());
- }
- }
- return bytes_available;
-}
+ CFStringRef bundleIDCFStr =
+ CopyBundleIDForPath(app_bundle_path.c_str(), attach_err);
+ std::string bundleIDStr;
+ CFString::UTF8(bundleIDCFStr, bundleIDStr);
+ DNBLogThreadedIf(LOG_PROCESS,
+ "CopyBundleIDForPath (%s, err_str) returned @\"%s\"",
+ app_bundle_path.c_str(), bundleIDStr.c_str());
+ if (bundleIDCFStr == NULL) {
+ return NULL;
+ }
-void *
-MachProcess::ProfileThread(void *arg)
-{
- MachProcess *proc = (MachProcess*) arg;
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( arg = %p ) thread starting...", __FUNCTION__, arg);
+#if defined(WITH_FBS)
+ if (launch_flavor == eLaunchFlavorFBS) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-#if defined (__APPLE__)
- pthread_setname_np ("performance profiling thread");
-#endif
+ NSString *stdio_path = nil;
+ NSFileManager *file_manager = [NSFileManager defaultManager];
+ const char *null_path = "/dev/null";
+ stdio_path =
+ [file_manager stringWithFileSystemRepresentation:null_path
+ length:strlen(null_path)];
- while (proc->IsProfilingEnabled())
- {
- nub_state_t state = proc->GetState();
- if (state == eStateRunning)
- {
- std::string data = proc->Task().GetProfileData(proc->GetProfileScanType());
- if (!data.empty())
- {
- proc->SignalAsyncProfileData(data.c_str());
- }
- }
- else if ((state == eStateUnloaded) || (state == eStateDetached) || (state == eStateUnloaded))
- {
- // Done. Get out of this thread.
- break;
- }
-
- // A simple way to set up the profile interval. We can also use select() or dispatch timer source if necessary.
- usleep(proc->ProfileInterval());
- }
- return NULL;
-}
+ NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+ NSMutableDictionary *options = [NSMutableDictionary dictionary];
+ DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: "
+ "@\"%s\",options include stdio path: \"%s\", "
+ "BKSDebugOptionKeyDebugOnNextLaunch & "
+ "BKSDebugOptionKeyWaitForDebugger )",
+ bundleIDStr.c_str(), null_path);
+
+ [debug_options setObject:stdio_path
+ forKey:FBSDebugOptionKeyStandardOutPath];
+ [debug_options setObject:stdio_path
+ forKey:FBSDebugOptionKeyStandardErrorPath];
+ [debug_options setObject:[NSNumber numberWithBool:YES]
+ forKey:FBSDebugOptionKeyWaitForDebugger];
+ [debug_options setObject:[NSNumber numberWithBool:YES]
+ forKey:FBSDebugOptionKeyDebugOnNextLaunch];
-pid_t
-MachProcess::AttachForDebug (pid_t pid, char *err_str, size_t err_len)
-{
- // Clear out and clean up from any current state
- Clear();
- if (pid != 0)
- {
- DNBError err;
- // Make sure the process exists...
- if (::getpgid (pid) < 0)
- {
- err.SetErrorToErrno();
- const char *err_cstr = err.AsString();
- ::snprintf (err_str, err_len, "%s", err_cstr ? err_cstr : "No such process");
- return INVALID_NUB_PROCESS;
- }
+ [options setObject:debug_options
+ forKey:FBSOpenApplicationOptionKeyDebuggingOptions];
- SetState(eStateAttaching);
- m_pid = pid;
- // Let ourselves know we are going to be using SBS or BKS if the correct flag bit is set...
-#if defined (WITH_FBS) || defined (WITH_BKS)
- bool found_app_flavor = false;
-#endif
-
-#if defined (WITH_FBS)
- if (!found_app_flavor && IsFBSProcess (pid))
- {
- found_app_flavor = true;
- m_flags |= eMachProcessFlagsUsingFBS;
- }
-#elif defined (WITH_BKS)
- if (!found_app_flavor && IsBKSProcess (pid))
- {
- found_app_flavor = true;
- m_flags |= eMachProcessFlagsUsingBKS;
- }
-#elif defined (WITH_SPRINGBOARD)
- if (IsSBProcess(pid))
- m_flags |= eMachProcessFlagsUsingSBS;
-#endif
- if (!m_task.StartExceptionThread(err))
- {
- const char *err_cstr = err.AsString();
- ::snprintf (err_str, err_len, "%s", err_cstr ? err_cstr : "unable to start the exception thread");
- DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", pid);
- m_pid = INVALID_NUB_PROCESS;
- return INVALID_NUB_PROCESS;
- }
+ FBSSystemService *system_service = [[FBSSystemService alloc] init];
- errno = 0;
- if (::ptrace (PT_ATTACHEXC, pid, 0, 0))
- err.SetError(errno);
- else
- err.Clear();
-
- if (err.Success())
- {
- m_flags |= eMachProcessFlagsAttached;
- // Sleep a bit to let the exception get received and set our process status
- // to stopped.
- ::usleep(250000);
- DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", pid);
- return m_pid;
- }
- else
- {
- ::snprintf (err_str, err_len, "%s", err.AsString());
- DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", pid);
- }
- }
- return INVALID_NUB_PROCESS;
-}
+ mach_port_t client_port = [system_service createClientPort];
+ __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
+ __block FBSOpenApplicationErrorCode attach_error_code =
+ FBSOpenApplicationErrorCodeNone;
-Genealogy::ThreadActivitySP
-MachProcess::GetGenealogyInfoForThread (nub_thread_t tid, bool &timed_out)
-{
- return m_activities.GetGenealogyInfoForThread (m_pid, tid, m_thread_list, m_task.TaskPort(), timed_out);
-}
+ NSString *bundleIDNSStr = (NSString *)bundleIDCFStr;
-Genealogy::ProcessExecutableInfoSP
-MachProcess::GetGenealogyImageInfo (size_t idx)
-{
- return m_activities.GetProcessExecutableInfosAtIndex (idx);
-}
+ [system_service openApplication:bundleIDNSStr
+ options:options
+ clientPort:client_port
+ withResult:^(NSError *error) {
+ // The system service will cleanup the client port we
+ // created for us.
+ if (error)
+ attach_error_code =
+ (FBSOpenApplicationErrorCode)[error code];
+
+ [system_service release];
+ dispatch_semaphore_signal(semaphore);
+ }];
-bool
-MachProcess::GetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch)
-{
-#if defined (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000)
- return false;
-#else
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ const uint32_t timeout_secs = 9;
- NSOperatingSystemVersion vers = [[NSProcessInfo processInfo] operatingSystemVersion];
- if (major)
- *major = vers.majorVersion;
- if (minor)
- *minor = vers.minorVersion;
- if (patch)
- *patch = vers.patchVersion;
+ dispatch_time_t timeout =
+ dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC);
+ long success = dispatch_semaphore_wait(semaphore, timeout) == 0;
+
+ if (!success) {
+ DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str());
+ attach_err.SetErrorString(
+ "debugserver timed out waiting for openApplication to complete.");
+ attach_err.SetError(OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
+ } else if (attach_error_code != FBSOpenApplicationErrorCodeNone) {
+ SetFBSError(attach_error_code, attach_err);
+ DNBLogError("unable to launch the application with CFBundleIdentifier "
+ "'%s' bks_error = %ld",
+ bundleIDStr.c_str(), (NSInteger)attach_error_code);
+ }
+ dispatch_release(semaphore);
[pool drain];
-
- return true;
+ }
#endif
-}
+#if defined(WITH_BKS)
+ if (launch_flavor == eLaunchFlavorBKS) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-// Do the process specific setup for attach. If this returns NULL, then there's no
-// platform specific stuff to be done to wait for the attach. If you get non-null,
-// pass that token to the CheckForProcess method, and then to CleanupAfterAttach.
+ NSString *stdio_path = nil;
+ NSFileManager *file_manager = [NSFileManager defaultManager];
+ const char *null_path = "/dev/null";
+ stdio_path =
+ [file_manager stringWithFileSystemRepresentation:null_path
+ length:strlen(null_path)];
-// Call PrepareForAttach before attaching to a process that has not yet launched
-// This returns a token that can be passed to CheckForProcess, and to CleanupAfterAttach.
-// You should call CleanupAfterAttach to free the token, and do whatever other
-// cleanup seems good.
+ NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+ NSMutableDictionary *options = [NSMutableDictionary dictionary];
-const void *
-MachProcess::PrepareForAttach (const char *path, nub_launch_flavor_t launch_flavor, bool waitfor, DNBError &attach_err)
-{
-#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS)
- // Tell SpringBoard to halt the next launch of this application on startup.
+ DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: "
+ "@\"%s\",options include stdio path: \"%s\", "
+ "BKSDebugOptionKeyDebugOnNextLaunch & "
+ "BKSDebugOptionKeyWaitForDebugger )",
+ bundleIDStr.c_str(), null_path);
+
+ [debug_options setObject:stdio_path
+ forKey:BKSDebugOptionKeyStandardOutPath];
+ [debug_options setObject:stdio_path
+ forKey:BKSDebugOptionKeyStandardErrorPath];
+ [debug_options setObject:[NSNumber numberWithBool:YES]
+ forKey:BKSDebugOptionKeyWaitForDebugger];
+ [debug_options setObject:[NSNumber numberWithBool:YES]
+ forKey:BKSDebugOptionKeyDebugOnNextLaunch];
- if (!waitfor)
- return NULL;
+ [options setObject:debug_options
+ forKey:BKSOpenApplicationOptionKeyDebuggingOptions];
- const char *app_ext = strstr(path, ".app");
- const bool is_app = app_ext != NULL && (app_ext[4] == '\0' || app_ext[4] == '/');
- if (!is_app)
- {
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::PrepareForAttach(): path '%s' doesn't contain .app, "
- "we can't tell springboard to wait for launch...",
- path);
- return NULL;
- }
+ BKSSystemService *system_service = [[BKSSystemService alloc] init];
-#if defined (WITH_FBS)
- if (launch_flavor == eLaunchFlavorDefault)
- launch_flavor = eLaunchFlavorFBS;
- if (launch_flavor != eLaunchFlavorFBS)
- return NULL;
-#elif defined (WITH_BKS)
- if (launch_flavor == eLaunchFlavorDefault)
- launch_flavor = eLaunchFlavorBKS;
- if (launch_flavor != eLaunchFlavorBKS)
- return NULL;
-#elif defined (WITH_SPRINGBOARD)
- if (launch_flavor == eLaunchFlavorDefault)
- launch_flavor = eLaunchFlavorSpringBoard;
- if (launch_flavor != eLaunchFlavorSpringBoard)
- return NULL;
-#endif
+ mach_port_t client_port = [system_service createClientPort];
+ __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
+ __block BKSOpenApplicationErrorCode attach_error_code =
+ BKSOpenApplicationErrorCodeNone;
- std::string app_bundle_path(path, app_ext + strlen(".app"));
+ NSString *bundleIDNSStr = (NSString *)bundleIDCFStr;
- CFStringRef bundleIDCFStr = CopyBundleIDForPath (app_bundle_path.c_str (), attach_err);
- std::string bundleIDStr;
- CFString::UTF8(bundleIDCFStr, bundleIDStr);
- DNBLogThreadedIf(LOG_PROCESS,
- "CopyBundleIDForPath (%s, err_str) returned @\"%s\"",
- app_bundle_path.c_str (),
- bundleIDStr.c_str());
+ [system_service openApplication:bundleIDNSStr
+ options:options
+ clientPort:client_port
+ withResult:^(NSError *error) {
+ // The system service will cleanup the client port we
+ // created for us.
+ if (error)
+ attach_error_code =
+ (BKSOpenApplicationErrorCode)[error code];
+
+ [system_service release];
+ dispatch_semaphore_signal(semaphore);
+ }];
- if (bundleIDCFStr == NULL)
- {
- return NULL;
- }
+ const uint32_t timeout_secs = 9;
-#if defined (WITH_FBS)
- if (launch_flavor == eLaunchFlavorFBS)
- {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSString *stdio_path = nil;
- NSFileManager *file_manager = [NSFileManager defaultManager];
- const char *null_path = "/dev/null";
- stdio_path = [file_manager stringWithFileSystemRepresentation: null_path length: strlen(null_path)];
-
- NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
- NSMutableDictionary *options = [NSMutableDictionary dictionary];
-
- DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: @\"%s\",options include stdio path: \"%s\", "
- "BKSDebugOptionKeyDebugOnNextLaunch & BKSDebugOptionKeyWaitForDebugger )",
- bundleIDStr.c_str(),
- null_path);
-
- [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardOutPath];
- [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardErrorPath];
- [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyWaitForDebugger];
- [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyDebugOnNextLaunch];
-
- [options setObject: debug_options forKey: FBSOpenApplicationOptionKeyDebuggingOptions];
-
- FBSSystemService *system_service = [[FBSSystemService alloc] init];
-
- mach_port_t client_port = [system_service createClientPort];
- __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- __block FBSOpenApplicationErrorCode attach_error_code = FBSOpenApplicationErrorCodeNone;
-
- NSString *bundleIDNSStr = (NSString *) bundleIDCFStr;
-
- [system_service openApplication: bundleIDNSStr
- options: options
- clientPort: client_port
- withResult: ^(NSError *error)
- {
- // The system service will cleanup the client port we created for us.
- if (error)
- attach_error_code = (FBSOpenApplicationErrorCode)[error code];
-
- [system_service release];
- dispatch_semaphore_signal(semaphore);
- }
- ];
-
- const uint32_t timeout_secs = 9;
-
- dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC);
-
- long success = dispatch_semaphore_wait(semaphore, timeout) == 0;
-
- if (!success)
- {
- DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str());
- attach_err.SetErrorString("debugserver timed out waiting for openApplication to complete.");
- attach_err.SetError (OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
- }
- else if (attach_error_code != FBSOpenApplicationErrorCodeNone)
- {
- SetFBSError (attach_error_code, attach_err);
- DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %ld",
- bundleIDStr.c_str(),
- (NSInteger) attach_error_code);
- }
- dispatch_release(semaphore);
- [pool drain];
- }
-#endif
-#if defined (WITH_BKS)
- if (launch_flavor == eLaunchFlavorBKS)
- {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSString *stdio_path = nil;
- NSFileManager *file_manager = [NSFileManager defaultManager];
- const char *null_path = "/dev/null";
- stdio_path = [file_manager stringWithFileSystemRepresentation: null_path length: strlen(null_path)];
-
- NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
- NSMutableDictionary *options = [NSMutableDictionary dictionary];
-
- DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: @\"%s\",options include stdio path: \"%s\", "
- "BKSDebugOptionKeyDebugOnNextLaunch & BKSDebugOptionKeyWaitForDebugger )",
- bundleIDStr.c_str(),
- null_path);
-
- [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardOutPath];
- [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardErrorPath];
- [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyWaitForDebugger];
- [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyDebugOnNextLaunch];
-
- [options setObject: debug_options forKey: BKSOpenApplicationOptionKeyDebuggingOptions];
-
- BKSSystemService *system_service = [[BKSSystemService alloc] init];
-
- mach_port_t client_port = [system_service createClientPort];
- __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- __block BKSOpenApplicationErrorCode attach_error_code = BKSOpenApplicationErrorCodeNone;
-
- NSString *bundleIDNSStr = (NSString *) bundleIDCFStr;
-
- [system_service openApplication: bundleIDNSStr
- options: options
- clientPort: client_port
- withResult: ^(NSError *error)
- {
- // The system service will cleanup the client port we created for us.
- if (error)
- attach_error_code = (BKSOpenApplicationErrorCode)[error code];
-
- [system_service release];
- dispatch_semaphore_signal(semaphore);
- }
- ];
-
- const uint32_t timeout_secs = 9;
-
- dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC);
-
- long success = dispatch_semaphore_wait(semaphore, timeout) == 0;
-
- if (!success)
- {
- DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str());
- attach_err.SetErrorString("debugserver timed out waiting for openApplication to complete.");
- attach_err.SetError (OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
- }
- else if (attach_error_code != BKSOpenApplicationErrorCodeNone)
- {
- SetBKSError (attach_error_code, attach_err);
- DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %ld",
- bundleIDStr.c_str(),
- attach_error_code);
- }
- dispatch_release(semaphore);
- [pool drain];
+ dispatch_time_t timeout =
+ dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC);
+
+ long success = dispatch_semaphore_wait(semaphore, timeout) == 0;
+
+ if (!success) {
+ DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str());
+ attach_err.SetErrorString(
+ "debugserver timed out waiting for openApplication to complete.");
+ attach_err.SetError(OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
+ } else if (attach_error_code != BKSOpenApplicationErrorCodeNone) {
+ SetBKSError(attach_error_code, attach_err);
+ DNBLogError("unable to launch the application with CFBundleIdentifier "
+ "'%s' bks_error = %ld",
+ bundleIDStr.c_str(), attach_error_code);
}
+ dispatch_release(semaphore);
+ [pool drain];
+ }
#endif
-#if defined (WITH_SPRINGBOARD)
- if (launch_flavor == eLaunchFlavorSpringBoard)
- {
- SBSApplicationLaunchError sbs_error = 0;
-
- const char *stdout_err = "/dev/null";
- CFString stdio_path;
- stdio_path.SetFileSystemRepresentation (stdout_err);
-
- DNBLogThreadedIf(LOG_PROCESS, "SBSLaunchApplicationForDebugging ( @\"%s\" , NULL, NULL, NULL, @\"%s\", @\"%s\", "
- "SBSApplicationDebugOnNextLaunch | SBSApplicationLaunchWaitForDebugger )",
- bundleIDStr.c_str(),
- stdout_err,
- stdout_err);
-
- sbs_error = SBSLaunchApplicationForDebugging (bundleIDCFStr,
- (CFURLRef)NULL, // openURL
- NULL, // launch_argv.get(),
- NULL, // launch_envp.get(), // CFDictionaryRef environment
- stdio_path.get(),
- stdio_path.get(),
- SBSApplicationDebugOnNextLaunch | SBSApplicationLaunchWaitForDebugger);
-
- if (sbs_error != SBSApplicationLaunchErrorSuccess)
- {
- attach_err.SetError(sbs_error, DNBError::SpringBoard);
- return NULL;
- }
+#if defined(WITH_SPRINGBOARD)
+ if (launch_flavor == eLaunchFlavorSpringBoard) {
+ SBSApplicationLaunchError sbs_error = 0;
+
+ const char *stdout_err = "/dev/null";
+ CFString stdio_path;
+ stdio_path.SetFileSystemRepresentation(stdout_err);
+
+ DNBLogThreadedIf(LOG_PROCESS, "SBSLaunchApplicationForDebugging ( @\"%s\" "
+ ", NULL, NULL, NULL, @\"%s\", @\"%s\", "
+ "SBSApplicationDebugOnNextLaunch | "
+ "SBSApplicationLaunchWaitForDebugger )",
+ bundleIDStr.c_str(), stdout_err, stdout_err);
+
+ sbs_error = SBSLaunchApplicationForDebugging(
+ bundleIDCFStr,
+ (CFURLRef)NULL, // openURL
+ NULL, // launch_argv.get(),
+ NULL, // launch_envp.get(), // CFDictionaryRef environment
+ stdio_path.get(), stdio_path.get(),
+ SBSApplicationDebugOnNextLaunch | SBSApplicationLaunchWaitForDebugger);
+
+ if (sbs_error != SBSApplicationLaunchErrorSuccess) {
+ attach_err.SetError(sbs_error, DNBError::SpringBoard);
+ return NULL;
}
+ }
#endif // WITH_SPRINGBOARD
- DNBLogThreadedIf(LOG_PROCESS, "Successfully set DebugOnNextLaunch.");
- return bundleIDCFStr;
-# else // !(defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS))
+ DNBLogThreadedIf(LOG_PROCESS, "Successfully set DebugOnNextLaunch.");
+ return bundleIDCFStr;
+#else // !(defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined
+ // (WITH_FBS))
return NULL;
#endif
}
@@ -2753,1148 +2729,1097 @@ MachProcess::PrepareForAttach (const cha
// for that token, then the pid will be returned, otherwise INVALID_NUB_PROCESS
// will be returned.
-nub_process_t
-MachProcess::CheckForProcess (const void *attach_token, nub_launch_flavor_t launch_flavor)
-{
- if (attach_token == NULL)
- return INVALID_NUB_PROCESS;
-
-#if defined (WITH_FBS)
- if (launch_flavor == eLaunchFlavorFBS)
- {
- NSString *bundleIDNSStr = (NSString *) attach_token;
- FBSSystemService *systemService = [[FBSSystemService alloc] init];
- pid_t pid = [systemService pidForApplication: bundleIDNSStr];
- [systemService release];
- if (pid == 0)
- return INVALID_NUB_PROCESS;
- else
- return pid;
- }
+nub_process_t MachProcess::CheckForProcess(const void *attach_token,
+ nub_launch_flavor_t launch_flavor) {
+ if (attach_token == NULL)
+ return INVALID_NUB_PROCESS;
+
+#if defined(WITH_FBS)
+ if (launch_flavor == eLaunchFlavorFBS) {
+ NSString *bundleIDNSStr = (NSString *)attach_token;
+ FBSSystemService *systemService = [[FBSSystemService alloc] init];
+ pid_t pid = [systemService pidForApplication:bundleIDNSStr];
+ [systemService release];
+ if (pid == 0)
+ return INVALID_NUB_PROCESS;
+ else
+ return pid;
+ }
#endif
-#if defined (WITH_BKS)
- if (launch_flavor == eLaunchFlavorBKS)
- {
- NSString *bundleIDNSStr = (NSString *) attach_token;
+#if defined(WITH_BKS)
+ if (launch_flavor == eLaunchFlavorBKS) {
+ NSString *bundleIDNSStr = (NSString *)attach_token;
BKSSystemService *systemService = [[BKSSystemService alloc] init];
- pid_t pid = [systemService pidForApplication: bundleIDNSStr];
+ pid_t pid = [systemService pidForApplication:bundleIDNSStr];
[systemService release];
if (pid == 0)
- return INVALID_NUB_PROCESS;
+ return INVALID_NUB_PROCESS;
else
- return pid;
- }
+ return pid;
+ }
#endif
-#if defined (WITH_SPRINGBOARD)
- if (launch_flavor == eLaunchFlavorSpringBoard)
- {
- CFStringRef bundleIDCFStr = (CFStringRef) attach_token;
+#if defined(WITH_SPRINGBOARD)
+ if (launch_flavor == eLaunchFlavorSpringBoard) {
+ CFStringRef bundleIDCFStr = (CFStringRef)attach_token;
Boolean got_it;
nub_process_t attach_pid;
got_it = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &attach_pid);
if (got_it)
- return attach_pid;
+ return attach_pid;
else
- return INVALID_NUB_PROCESS;
- }
+ return INVALID_NUB_PROCESS;
+ }
#endif
- return INVALID_NUB_PROCESS;
+ return INVALID_NUB_PROCESS;
}
-// Call this to clean up after you have either attached or given up on the attach.
+// Call this to clean up after you have either attached or given up on the
+// attach.
// Pass true for success if you have attached, false if you have not.
// The token will also be freed at this point, so you can't use it after calling
// this method.
-void
-MachProcess::CleanupAfterAttach (const void *attach_token, nub_launch_flavor_t launch_flavor, bool success, DNBError &err_str)
-{
- if (attach_token == NULL)
- return;
+void MachProcess::CleanupAfterAttach(const void *attach_token,
+ nub_launch_flavor_t launch_flavor,
+ bool success, DNBError &err_str) {
+ if (attach_token == NULL)
+ return;
-#if defined (WITH_FBS)
- if (launch_flavor == eLaunchFlavorFBS)
- {
- if (!success)
- {
- FBSCleanupAfterAttach (attach_token, err_str);
- }
- CFRelease((CFStringRef) attach_token);
+#if defined(WITH_FBS)
+ if (launch_flavor == eLaunchFlavorFBS) {
+ if (!success) {
+ FBSCleanupAfterAttach(attach_token, err_str);
}
+ CFRelease((CFStringRef)attach_token);
+ }
#endif
-#if defined (WITH_BKS)
+#if defined(WITH_BKS)
- if (launch_flavor == eLaunchFlavorBKS)
- {
- if (!success)
- {
- BKSCleanupAfterAttach (attach_token, err_str);
- }
- CFRelease((CFStringRef) attach_token);
- }
-#endif
-
-#if defined (WITH_SPRINGBOARD)
- // Tell SpringBoard to cancel the debug on next launch of this application
- // if we failed to attach
- if (launch_flavor == eMachProcessFlagsUsingSpringBoard)
- {
- if (!success)
- {
- SBSApplicationLaunchError sbs_error = 0;
- CFStringRef bundleIDCFStr = (CFStringRef) attach_token;
-
- sbs_error = SBSLaunchApplicationForDebugging (bundleIDCFStr,
- (CFURLRef)NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- SBSApplicationCancelDebugOnNextLaunch);
-
- if (sbs_error != SBSApplicationLaunchErrorSuccess)
- {
- err_str.SetError(sbs_error, DNBError::SpringBoard);
- return;
- }
+ if (launch_flavor == eLaunchFlavorBKS) {
+ if (!success) {
+ BKSCleanupAfterAttach(attach_token, err_str);
}
+ CFRelease((CFStringRef)attach_token);
+ }
+#endif
+
+#if defined(WITH_SPRINGBOARD)
+ // Tell SpringBoard to cancel the debug on next launch of this application
+ // if we failed to attach
+ if (launch_flavor == eMachProcessFlagsUsingSpringBoard) {
+ if (!success) {
+ SBSApplicationLaunchError sbs_error = 0;
+ CFStringRef bundleIDCFStr = (CFStringRef)attach_token;
+
+ sbs_error = SBSLaunchApplicationForDebugging(
+ bundleIDCFStr, (CFURLRef)NULL, NULL, NULL, NULL, NULL,
+ SBSApplicationCancelDebugOnNextLaunch);
- CFRelease((CFStringRef) attach_token);
+ if (sbs_error != SBSApplicationLaunchErrorSuccess) {
+ err_str.SetError(sbs_error, DNBError::SpringBoard);
+ return;
+ }
}
+
+ CFRelease((CFStringRef)attach_token);
+ }
#endif
}
-pid_t
-MachProcess::LaunchForDebug
-(
- const char *path,
- char const *argv[],
- char const *envp[],
- const char *working_directory, // NULL => don't change, non-NULL => set working directory for inferior to this
- const char *stdin_path,
- const char *stdout_path,
- const char *stderr_path,
- bool no_stdio,
- nub_launch_flavor_t launch_flavor,
- int disable_aslr,
- const char *event_data,
- DNBError &launch_err
-)
-{
- // Clear out and clean up from any current state
- Clear();
-
- DNBLogThreadedIf(LOG_PROCESS, "%s( path = '%s', argv = %p, envp = %p, launch_flavor = %u, disable_aslr = %d )", __FUNCTION__, path, argv, envp, launch_flavor, disable_aslr);
-
- // Fork a child process for debugging
- SetState(eStateLaunching);
-
- switch (launch_flavor)
- {
- case eLaunchFlavorForkExec:
- m_pid = MachProcess::ForkChildForPTraceDebugging (path, argv, envp, this, launch_err);
- break;
+pid_t MachProcess::LaunchForDebug(
+ const char *path, char const *argv[], char const *envp[],
+ const char *working_directory, // NULL => don't change, non-NULL => set
+ // working directory for inferior to this
+ const char *stdin_path, const char *stdout_path, const char *stderr_path,
+ bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr,
+ const char *event_data, DNBError &launch_err) {
+ // Clear out and clean up from any current state
+ Clear();
+
+ DNBLogThreadedIf(LOG_PROCESS, "%s( path = '%s', argv = %p, envp = %p, "
+ "launch_flavor = %u, disable_aslr = %d )",
+ __FUNCTION__, path, argv, envp, launch_flavor, disable_aslr);
+
+ // Fork a child process for debugging
+ SetState(eStateLaunching);
+
+ switch (launch_flavor) {
+ case eLaunchFlavorForkExec:
+ m_pid = MachProcess::ForkChildForPTraceDebugging(path, argv, envp, this,
+ launch_err);
+ break;
#ifdef WITH_FBS
- case eLaunchFlavorFBS:
- {
- const char *app_ext = strstr(path, ".app");
- if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/'))
- {
- std::string app_bundle_path(path, app_ext + strlen(".app"));
- m_flags |= eMachProcessFlagsUsingFBS;
- if (BoardServiceLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, event_data, launch_err) != 0)
- return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid.
- else
- break; // We tried a FBS launch, but didn't succeed lets get out
- }
- }
- break;
+ case eLaunchFlavorFBS: {
+ const char *app_ext = strstr(path, ".app");
+ if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) {
+ std::string app_bundle_path(path, app_ext + strlen(".app"));
+ m_flags |= eMachProcessFlagsUsingFBS;
+ if (BoardServiceLaunchForDebug(app_bundle_path.c_str(), argv, envp,
+ no_stdio, disable_aslr, event_data,
+ launch_err) != 0)
+ return m_pid; // A successful SBLaunchForDebug() returns and assigns a
+ // non-zero m_pid.
+ else
+ break; // We tried a FBS launch, but didn't succeed lets get out
+ }
+ } break;
#endif
#ifdef WITH_BKS
- case eLaunchFlavorBKS:
- {
- const char *app_ext = strstr(path, ".app");
- if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/'))
- {
- std::string app_bundle_path(path, app_ext + strlen(".app"));
- m_flags |= eMachProcessFlagsUsingBKS;
- if (BoardServiceLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, event_data, launch_err) != 0)
- return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid.
- else
- break; // We tried a BKS launch, but didn't succeed lets get out
- }
- }
- break;
+ case eLaunchFlavorBKS: {
+ const char *app_ext = strstr(path, ".app");
+ if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) {
+ std::string app_bundle_path(path, app_ext + strlen(".app"));
+ m_flags |= eMachProcessFlagsUsingBKS;
+ if (BoardServiceLaunchForDebug(app_bundle_path.c_str(), argv, envp,
+ no_stdio, disable_aslr, event_data,
+ launch_err) != 0)
+ return m_pid; // A successful SBLaunchForDebug() returns and assigns a
+ // non-zero m_pid.
+ else
+ break; // We tried a BKS launch, but didn't succeed lets get out
+ }
+ } break;
#endif
#ifdef WITH_SPRINGBOARD
- case eLaunchFlavorSpringBoard:
- {
- // .../whatever.app/whatever ?
- // Or .../com.apple.whatever.app/whatever -- be careful of ".app" in "com.apple.whatever" here
- const char *app_ext = strstr (path, ".app/");
- if (app_ext == NULL)
- {
- // .../whatever.app ?
- int len = strlen (path);
- if (len > 5)
- {
- if (strcmp (path + len - 4, ".app") == 0)
- {
- app_ext = path + len - 4;
- }
- }
- }
- if (app_ext)
- {
- std::string app_bundle_path(path, app_ext + strlen(".app"));
- if (SBLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, launch_err) != 0)
- return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid.
- else
- break; // We tried a springboard launch, but didn't succeed lets get out
- }
- }
- break;
+ case eLaunchFlavorSpringBoard: {
+ // .../whatever.app/whatever ?
+ // Or .../com.apple.whatever.app/whatever -- be careful of ".app" in
+ // "com.apple.whatever" here
+ const char *app_ext = strstr(path, ".app/");
+ if (app_ext == NULL) {
+ // .../whatever.app ?
+ int len = strlen(path);
+ if (len > 5) {
+ if (strcmp(path + len - 4, ".app") == 0) {
+ app_ext = path + len - 4;
+ }
+ }
+ }
+ if (app_ext) {
+ std::string app_bundle_path(path, app_ext + strlen(".app"));
+ if (SBLaunchForDebug(app_bundle_path.c_str(), argv, envp, no_stdio,
+ disable_aslr, launch_err) != 0)
+ return m_pid; // A successful SBLaunchForDebug() returns and assigns a
+ // non-zero m_pid.
+ else
+ break; // We tried a springboard launch, but didn't succeed lets get out
+ }
+ } break;
#endif
- case eLaunchFlavorPosixSpawn:
- m_pid = MachProcess::PosixSpawnChildForPTraceDebugging (path,
- DNBArchProtocol::GetArchitecture (),
- argv,
- envp,
- working_directory,
- stdin_path,
- stdout_path,
- stderr_path,
- no_stdio,
- this,
- disable_aslr,
- launch_err);
- break;
+ case eLaunchFlavorPosixSpawn:
+ m_pid = MachProcess::PosixSpawnChildForPTraceDebugging(
+ path, DNBArchProtocol::GetArchitecture(), argv, envp, working_directory,
+ stdin_path, stdout_path, stderr_path, no_stdio, this, disable_aslr,
+ launch_err);
+ break;
+
+ default:
+ // Invalid launch
+ launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic);
+ return INVALID_NUB_PROCESS;
+ }
- default:
- // Invalid launch
+ if (m_pid == INVALID_NUB_PROCESS) {
+ // If we don't have a valid process ID and no one has set the error,
+ // then return a generic error
+ if (launch_err.Success())
+ launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic);
+ } else {
+ m_path = path;
+ size_t i;
+ char const *arg;
+ for (i = 0; (arg = argv[i]) != NULL; i++)
+ m_args.push_back(arg);
+
+ m_task.StartExceptionThread(launch_err);
+ if (launch_err.Fail()) {
+ if (launch_err.AsString() == NULL)
+ launch_err.SetErrorString("unable to start the exception thread");
+ DNBLog("Could not get inferior's Mach exception port, sending ptrace "
+ "PT_KILL and exiting.");
+ ::ptrace(PT_KILL, m_pid, 0, 0);
+ m_pid = INVALID_NUB_PROCESS;
+ return INVALID_NUB_PROCESS;
+ }
+
+ StartSTDIOThread();
+
+ if (launch_flavor == eLaunchFlavorPosixSpawn) {
+
+ SetState(eStateAttaching);
+ errno = 0;
+ int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0);
+ if (err == 0) {
+ m_flags |= eMachProcessFlagsAttached;
+ DNBLogThreadedIf(LOG_PROCESS, "successfully spawned pid %d", m_pid);
+ launch_err.Clear();
+ } else {
+ SetState(eStateExited);
+ DNBError ptrace_err(errno, DNBError::POSIX);
+ DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to spawned pid "
+ "%d (err = %i, errno = %i (%s))",
+ m_pid, err, ptrace_err.Error(), ptrace_err.AsString());
launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic);
- return INVALID_NUB_PROCESS;
- }
-
- if (m_pid == INVALID_NUB_PROCESS)
- {
- // If we don't have a valid process ID and no one has set the error,
- // then return a generic error
- if (launch_err.Success())
- launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic);
- }
- else
- {
- m_path = path;
- size_t i;
- char const *arg;
- for (i=0; (arg = argv[i]) != NULL; i++)
- m_args.push_back(arg);
-
- m_task.StartExceptionThread(launch_err);
- if (launch_err.Fail())
- {
- if (launch_err.AsString() == NULL)
- launch_err.SetErrorString("unable to start the exception thread");
- DNBLog ("Could not get inferior's Mach exception port, sending ptrace PT_KILL and exiting.");
- ::ptrace (PT_KILL, m_pid, 0, 0);
- m_pid = INVALID_NUB_PROCESS;
- return INVALID_NUB_PROCESS;
- }
+ }
+ } else {
+ launch_err.Clear();
+ }
+ }
+ return m_pid;
+}
+
+pid_t MachProcess::PosixSpawnChildForPTraceDebugging(
+ const char *path, cpu_type_t cpu_type, char const *argv[],
+ char const *envp[], const char *working_directory, const char *stdin_path,
+ const char *stdout_path, const char *stderr_path, bool no_stdio,
+ MachProcess *process, int disable_aslr, DNBError &err) {
+ posix_spawnattr_t attr;
+ short flags;
+ DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv=%p, envp=%p, "
+ "working_dir=%s, stdin=%s, stdout=%s "
+ "stderr=%s, no-stdio=%i)",
+ __FUNCTION__, path, argv, envp, working_directory,
+ stdin_path, stdout_path, stderr_path, no_stdio);
+
+ err.SetError(::posix_spawnattr_init(&attr), DNBError::POSIX);
+ if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
+ err.LogThreaded("::posix_spawnattr_init ( &attr )");
+ if (err.Fail())
+ return INVALID_NUB_PROCESS;
- StartSTDIOThread();
+ flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETSIGDEF |
+ POSIX_SPAWN_SETSIGMASK;
+ if (disable_aslr)
+ flags |= _POSIX_SPAWN_DISABLE_ASLR;
+
+ sigset_t no_signals;
+ sigset_t all_signals;
+ sigemptyset(&no_signals);
+ sigfillset(&all_signals);
+ ::posix_spawnattr_setsigmask(&attr, &no_signals);
+ ::posix_spawnattr_setsigdefault(&attr, &all_signals);
+
+ err.SetError(::posix_spawnattr_setflags(&attr, flags), DNBError::POSIX);
+ if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
+ err.LogThreaded(
+ "::posix_spawnattr_setflags ( &attr, POSIX_SPAWN_START_SUSPENDED%s )",
+ flags & _POSIX_SPAWN_DISABLE_ASLR ? " | _POSIX_SPAWN_DISABLE_ASLR"
+ : "");
+ if (err.Fail())
+ return INVALID_NUB_PROCESS;
- if (launch_flavor == eLaunchFlavorPosixSpawn)
- {
+// Don't do this on SnowLeopard, _sometimes_ the TASK_BASIC_INFO will fail
+// and we will fail to continue with our process...
- SetState (eStateAttaching);
- errno = 0;
- int err = ::ptrace (PT_ATTACHEXC, m_pid, 0, 0);
- if (err == 0)
- {
- m_flags |= eMachProcessFlagsAttached;
- DNBLogThreadedIf(LOG_PROCESS, "successfully spawned pid %d", m_pid);
- launch_err.Clear();
- }
- else
- {
- SetState (eStateExited);
- DNBError ptrace_err(errno, DNBError::POSIX);
- DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to spawned pid %d (err = %i, errno = %i (%s))", m_pid, err, ptrace_err.Error(), ptrace_err.AsString());
- launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic);
- }
- }
- else
- {
- launch_err.Clear();
- }
- }
- return m_pid;
-}
+// On SnowLeopard we should set "DYLD_NO_PIE" in the inferior environment....
-pid_t
-MachProcess::PosixSpawnChildForPTraceDebugging
-(
- const char *path,
- cpu_type_t cpu_type,
- char const *argv[],
- char const *envp[],
- const char *working_directory,
- const char *stdin_path,
- const char *stdout_path,
- const char *stderr_path,
- bool no_stdio,
- MachProcess* process,
- int disable_aslr,
- DNBError& err
-)
-{
- posix_spawnattr_t attr;
- short flags;
- DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv=%p, envp=%p, working_dir=%s, stdin=%s, stdout=%s stderr=%s, no-stdio=%i)",
- __FUNCTION__,
- path,
- argv,
- envp,
- working_directory,
- stdin_path,
- stdout_path,
- stderr_path,
- no_stdio);
+#if !defined(__arm__)
- err.SetError( ::posix_spawnattr_init (&attr), DNBError::POSIX);
+ // We don't need to do this for ARM, and we really shouldn't now that we
+ // have multiple CPU subtypes and no posix_spawnattr call that allows us
+ // to set which CPU subtype to launch...
+ if (cpu_type != 0) {
+ size_t ocount = 0;
+ err.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu_type, &ocount),
+ DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
- err.LogThreaded("::posix_spawnattr_init ( &attr )");
- if (err.Fail())
- return INVALID_NUB_PROCESS;
-
- flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
- if (disable_aslr)
- flags |= _POSIX_SPAWN_DISABLE_ASLR;
-
- sigset_t no_signals;
- sigset_t all_signals;
- sigemptyset (&no_signals);
- sigfillset (&all_signals);
- ::posix_spawnattr_setsigmask(&attr, &no_signals);
- ::posix_spawnattr_setsigdefault(&attr, &all_signals);
-
- err.SetError( ::posix_spawnattr_setflags (&attr, flags), DNBError::POSIX);
+ err.LogThreaded("::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = "
+ "0x%8.8x, count => %llu )",
+ cpu_type, (uint64_t)ocount);
+
+ if (err.Fail() != 0 || ocount != 1)
+ return INVALID_NUB_PROCESS;
+ }
+#endif
+
+ PseudoTerminal pty;
+
+ posix_spawn_file_actions_t file_actions;
+ err.SetError(::posix_spawn_file_actions_init(&file_actions), DNBError::POSIX);
+ int file_actions_valid = err.Success();
+ if (!file_actions_valid || DNBLogCheckLogBit(LOG_PROCESS))
+ err.LogThreaded("::posix_spawn_file_actions_init ( &file_actions )");
+ int pty_error = -1;
+ pid_t pid = INVALID_NUB_PROCESS;
+ if (file_actions_valid) {
+ if (stdin_path == NULL && stdout_path == NULL && stderr_path == NULL &&
+ !no_stdio) {
+ pty_error = pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY);
+ if (pty_error == PseudoTerminal::success) {
+ stdin_path = stdout_path = stderr_path = pty.SlaveName();
+ }
+ }
+
+ // if no_stdio or std paths not supplied, then route to "/dev/null".
+ if (no_stdio || stdin_path == NULL || stdin_path[0] == '\0')
+ stdin_path = "/dev/null";
+ if (no_stdio || stdout_path == NULL || stdout_path[0] == '\0')
+ stdout_path = "/dev/null";
+ if (no_stdio || stderr_path == NULL || stderr_path[0] == '\0')
+ stderr_path = "/dev/null";
+
+ err.SetError(::posix_spawn_file_actions_addopen(&file_actions, STDIN_FILENO,
+ stdin_path,
+ O_RDONLY | O_NOCTTY, 0),
+ DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
- err.LogThreaded("::posix_spawnattr_setflags ( &attr, POSIX_SPAWN_START_SUSPENDED%s )", flags & _POSIX_SPAWN_DISABLE_ASLR ? " | _POSIX_SPAWN_DISABLE_ASLR" : "");
- if (err.Fail())
- return INVALID_NUB_PROCESS;
-
- // Don't do this on SnowLeopard, _sometimes_ the TASK_BASIC_INFO will fail
- // and we will fail to continue with our process...
-
- // On SnowLeopard we should set "DYLD_NO_PIE" in the inferior environment....
-
-#if !defined(__arm__)
-
- // We don't need to do this for ARM, and we really shouldn't now that we
- // have multiple CPU subtypes and no posix_spawnattr call that allows us
- // to set which CPU subtype to launch...
- if (cpu_type != 0)
- {
- size_t ocount = 0;
- err.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount), DNBError::POSIX);
- if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
- err.LogThreaded("::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu_type, (uint64_t)ocount);
-
- if (err.Fail() != 0 || ocount != 1)
- return INVALID_NUB_PROCESS;
+ err.LogThreaded("::posix_spawn_file_actions_addopen (&file_actions, "
+ "filedes=STDIN_FILENO, path='%s')",
+ stdin_path);
+
+ err.SetError(::posix_spawn_file_actions_addopen(
+ &file_actions, STDOUT_FILENO, stdout_path,
+ O_WRONLY | O_NOCTTY | O_CREAT, 0640),
+ DNBError::POSIX);
+ if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
+ err.LogThreaded("::posix_spawn_file_actions_addopen (&file_actions, "
+ "filedes=STDOUT_FILENO, path='%s')",
+ stdout_path);
+
+ err.SetError(::posix_spawn_file_actions_addopen(
+ &file_actions, STDERR_FILENO, stderr_path,
+ O_WRONLY | O_NOCTTY | O_CREAT, 0640),
+ DNBError::POSIX);
+ if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
+ err.LogThreaded("::posix_spawn_file_actions_addopen (&file_actions, "
+ "filedes=STDERR_FILENO, path='%s')",
+ stderr_path);
+
+ // TODO: Verify if we can set the working directory back immediately
+ // after the posix_spawnp call without creating a race condition???
+ if (working_directory)
+ ::chdir(working_directory);
+
+ err.SetError(::posix_spawnp(&pid, path, &file_actions, &attr,
+ (char *const *)argv, (char *const *)envp),
+ DNBError::POSIX);
+ if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
+ err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = "
+ "%p, attr = %p, argv = %p, envp = %p )",
+ pid, path, &file_actions, &attr, argv, envp);
+ } else {
+ // TODO: Verify if we can set the working directory back immediately
+ // after the posix_spawnp call without creating a race condition???
+ if (working_directory)
+ ::chdir(working_directory);
+
+ err.SetError(::posix_spawnp(&pid, path, NULL, &attr, (char *const *)argv,
+ (char *const *)envp),
+ DNBError::POSIX);
+ if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
+ err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = "
+ "%p, attr = %p, argv = %p, envp = %p )",
+ pid, path, NULL, &attr, argv, envp);
+ }
+
+ // We have seen some cases where posix_spawnp was returning a valid
+ // looking pid even when an error was returned, so clear it out
+ if (err.Fail())
+ pid = INVALID_NUB_PROCESS;
+
+ if (pty_error == 0) {
+ if (process != NULL) {
+ int master_fd = pty.ReleaseMasterFD();
+ process->SetChildFileDescriptors(master_fd, master_fd, master_fd);
}
-#endif
-
- PseudoTerminal pty;
-
- posix_spawn_file_actions_t file_actions;
- err.SetError( ::posix_spawn_file_actions_init (&file_actions), DNBError::POSIX);
- int file_actions_valid = err.Success();
- if (!file_actions_valid || DNBLogCheckLogBit(LOG_PROCESS))
- err.LogThreaded("::posix_spawn_file_actions_init ( &file_actions )");
- int pty_error = -1;
- pid_t pid = INVALID_NUB_PROCESS;
- if (file_actions_valid)
- {
- if (stdin_path == NULL && stdout_path == NULL && stderr_path == NULL && !no_stdio)
- {
- pty_error = pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY);
- if (pty_error == PseudoTerminal::success)
- {
- stdin_path = stdout_path = stderr_path = pty.SlaveName();
- }
- }
+ }
+ ::posix_spawnattr_destroy(&attr);
- // if no_stdio or std paths not supplied, then route to "/dev/null".
- if (no_stdio || stdin_path == NULL || stdin_path[0] == '\0')
- stdin_path = "/dev/null";
- if (no_stdio || stdout_path == NULL || stdout_path[0] == '\0')
- stdout_path = "/dev/null";
- if (no_stdio || stderr_path == NULL || stderr_path[0] == '\0')
- stderr_path = "/dev/null";
-
- err.SetError( ::posix_spawn_file_actions_addopen (&file_actions,
- STDIN_FILENO,
- stdin_path,
- O_RDONLY | O_NOCTTY,
- 0),
- DNBError::POSIX);
- if (err.Fail() || DNBLogCheckLogBit (LOG_PROCESS))
- err.LogThreaded ("::posix_spawn_file_actions_addopen (&file_actions, filedes=STDIN_FILENO, path='%s')", stdin_path);
-
- err.SetError( ::posix_spawn_file_actions_addopen (&file_actions,
- STDOUT_FILENO,
- stdout_path,
- O_WRONLY | O_NOCTTY | O_CREAT,
- 0640),
- DNBError::POSIX);
- if (err.Fail() || DNBLogCheckLogBit (LOG_PROCESS))
- err.LogThreaded ("::posix_spawn_file_actions_addopen (&file_actions, filedes=STDOUT_FILENO, path='%s')", stdout_path);
-
- err.SetError( ::posix_spawn_file_actions_addopen (&file_actions,
- STDERR_FILENO,
- stderr_path,
- O_WRONLY | O_NOCTTY | O_CREAT,
- 0640),
- DNBError::POSIX);
- if (err.Fail() || DNBLogCheckLogBit (LOG_PROCESS))
- err.LogThreaded ("::posix_spawn_file_actions_addopen (&file_actions, filedes=STDERR_FILENO, path='%s')", stderr_path);
-
- // TODO: Verify if we can set the working directory back immediately
- // after the posix_spawnp call without creating a race condition???
- if (working_directory)
- ::chdir (working_directory);
-
- err.SetError( ::posix_spawnp (&pid, path, &file_actions, &attr, (char * const*)argv, (char * const*)envp), DNBError::POSIX);
- if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
- err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, &file_actions, &attr, argv, envp);
- }
- else
- {
- // TODO: Verify if we can set the working directory back immediately
- // after the posix_spawnp call without creating a race condition???
- if (working_directory)
- ::chdir (working_directory);
-
- err.SetError( ::posix_spawnp (&pid, path, NULL, &attr, (char * const*)argv, (char * const*)envp), DNBError::POSIX);
- if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
- err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, NULL, &attr, argv, envp);
- }
-
- // We have seen some cases where posix_spawnp was returning a valid
- // looking pid even when an error was returned, so clear it out
- if (err.Fail())
- pid = INVALID_NUB_PROCESS;
-
- if (pty_error == 0)
- {
- if (process != NULL)
- {
- int master_fd = pty.ReleaseMasterFD();
- process->SetChildFileDescriptors(master_fd, master_fd, master_fd);
- }
- }
- ::posix_spawnattr_destroy (&attr);
+ if (pid != INVALID_NUB_PROCESS) {
+ cpu_type_t pid_cpu_type = MachProcess::GetCPUTypeForLocalProcess(pid);
+ DNBLogThreadedIf(LOG_PROCESS,
+ "MachProcess::%s ( ) pid=%i, cpu_type=0x%8.8x",
+ __FUNCTION__, pid, pid_cpu_type);
+ if (pid_cpu_type)
+ DNBArchProtocol::SetArchitecture(pid_cpu_type);
+ }
+
+ if (file_actions_valid) {
+ DNBError err2;
+ err2.SetError(::posix_spawn_file_actions_destroy(&file_actions),
+ DNBError::POSIX);
+ if (err2.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
+ err2.LogThreaded("::posix_spawn_file_actions_destroy ( &file_actions )");
+ }
+
+ return pid;
+}
+
+uint32_t MachProcess::GetCPUTypeForLocalProcess(pid_t pid) {
+ int mib[CTL_MAXNAME] = {
+ 0,
+ };
+ size_t len = CTL_MAXNAME;
+ if (::sysctlnametomib("sysctl.proc_cputype", mib, &len))
+ return 0;
- if (pid != INVALID_NUB_PROCESS)
- {
- cpu_type_t pid_cpu_type = MachProcess::GetCPUTypeForLocalProcess (pid);
- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( ) pid=%i, cpu_type=0x%8.8x", __FUNCTION__, pid, pid_cpu_type);
- if (pid_cpu_type)
- DNBArchProtocol::SetArchitecture (pid_cpu_type);
- }
-
- if (file_actions_valid)
- {
- DNBError err2;
- err2.SetError( ::posix_spawn_file_actions_destroy (&file_actions), DNBError::POSIX);
- if (err2.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
- err2.LogThreaded("::posix_spawn_file_actions_destroy ( &file_actions )");
- }
+ mib[len] = pid;
+ len++;
+ cpu_type_t cpu;
+ size_t cpu_len = sizeof(cpu);
+ if (::sysctl(mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0))
+ cpu = 0;
+ return cpu;
+}
+
+pid_t MachProcess::ForkChildForPTraceDebugging(const char *path,
+ char const *argv[],
+ char const *envp[],
+ MachProcess *process,
+ DNBError &launch_err) {
+ PseudoTerminal::Error pty_error = PseudoTerminal::success;
+
+ // Use a fork that ties the child process's stdin/out/err to a pseudo
+ // terminal so we can read it in our MachProcess::STDIOThread
+ // as unbuffered io.
+ PseudoTerminal pty;
+ pid_t pid = pty.Fork(pty_error);
+
+ if (pid < 0) {
+ //--------------------------------------------------------------
+ // Error during fork.
+ //--------------------------------------------------------------
return pid;
-}
-
-uint32_t
-MachProcess::GetCPUTypeForLocalProcess (pid_t pid)
-{
- int mib[CTL_MAXNAME]={0,};
- size_t len = CTL_MAXNAME;
- if (::sysctlnametomib("sysctl.proc_cputype", mib, &len))
- return 0;
-
- mib[len] = pid;
- len++;
-
- cpu_type_t cpu;
- size_t cpu_len = sizeof(cpu);
- if (::sysctl (mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0))
- cpu = 0;
- return cpu;
-}
-
-pid_t
-MachProcess::ForkChildForPTraceDebugging
-(
- const char *path,
- char const *argv[],
- char const *envp[],
- MachProcess* process,
- DNBError& launch_err
-)
-{
- PseudoTerminal::Error pty_error = PseudoTerminal::success;
-
- // Use a fork that ties the child process's stdin/out/err to a pseudo
- // terminal so we can read it in our MachProcess::STDIOThread
- // as unbuffered io.
- PseudoTerminal pty;
- pid_t pid = pty.Fork(pty_error);
-
- if (pid < 0)
- {
- //--------------------------------------------------------------
- // Error during fork.
- //--------------------------------------------------------------
- return pid;
- }
- else if (pid == 0)
- {
- //--------------------------------------------------------------
- // Child process
- //--------------------------------------------------------------
- ::ptrace (PT_TRACE_ME, 0, 0, 0); // Debug this process
- ::ptrace (PT_SIGEXC, 0, 0, 0); // Get BSD signals as mach exceptions
-
- // If our parent is setgid, lets make sure we don't inherit those
- // extra powers due to nepotism.
- if (::setgid (getgid ()) == 0)
- {
-
- // Let the child have its own process group. We need to execute
- // this call in both the child and parent to avoid a race condition
- // between the two processes.
- ::setpgid (0, 0); // Set the child process group to match its pid
-
- // Sleep a bit to before the exec call
- ::sleep (1);
-
- // Turn this process into
- ::execv (path, (char * const *)argv);
- }
- // Exit with error code. Child process should have taken
- // over in above exec call and if the exec fails it will
- // exit the child process below.
- ::exit (127);
+ } else if (pid == 0) {
+ //--------------------------------------------------------------
+ // Child process
+ //--------------------------------------------------------------
+ ::ptrace(PT_TRACE_ME, 0, 0, 0); // Debug this process
+ ::ptrace(PT_SIGEXC, 0, 0, 0); // Get BSD signals as mach exceptions
+
+ // If our parent is setgid, lets make sure we don't inherit those
+ // extra powers due to nepotism.
+ if (::setgid(getgid()) == 0) {
+
+ // Let the child have its own process group. We need to execute
+ // this call in both the child and parent to avoid a race condition
+ // between the two processes.
+ ::setpgid(0, 0); // Set the child process group to match its pid
+
+ // Sleep a bit to before the exec call
+ ::sleep(1);
+
+ // Turn this process into
+ ::execv(path, (char *const *)argv);
+ }
+ // Exit with error code. Child process should have taken
+ // over in above exec call and if the exec fails it will
+ // exit the child process below.
+ ::exit(127);
+ } else {
+ //--------------------------------------------------------------
+ // Parent process
+ //--------------------------------------------------------------
+ // Let the child have its own process group. We need to execute
+ // this call in both the child and parent to avoid a race condition
+ // between the two processes.
+ ::setpgid(pid, pid); // Set the child process group to match its pid
+
+ if (process != NULL) {
+ // Release our master pty file descriptor so the pty class doesn't
+ // close it and so we can continue to use it in our STDIO thread
+ int master_fd = pty.ReleaseMasterFD();
+ process->SetChildFileDescriptors(master_fd, master_fd, master_fd);
}
- else
- {
- //--------------------------------------------------------------
- // Parent process
- //--------------------------------------------------------------
- // Let the child have its own process group. We need to execute
- // this call in both the child and parent to avoid a race condition
- // between the two processes.
- ::setpgid (pid, pid); // Set the child process group to match its pid
-
- if (process != NULL)
- {
- // Release our master pty file descriptor so the pty class doesn't
- // close it and so we can continue to use it in our STDIO thread
- int master_fd = pty.ReleaseMasterFD();
- process->SetChildFileDescriptors(master_fd, master_fd, master_fd);
- }
- }
- return pid;
+ }
+ return pid;
}
-#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS)
+#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) || defined(WITH_FBS)
// This returns a CFRetained pointer to the Bundle ID for app_bundle_path,
// or NULL if there was some problem getting the bundle id.
-static CFStringRef
-CopyBundleIDForPath (const char *app_bundle_path, DNBError &err_str)
-{
- CFBundle bundle(app_bundle_path);
- CFStringRef bundleIDCFStr = bundle.GetIdentifier();
- std::string bundleID;
- if (CFString::UTF8(bundleIDCFStr, bundleID) == NULL)
- {
- struct stat app_bundle_stat;
- char err_msg[PATH_MAX];
-
- if (::stat (app_bundle_path, &app_bundle_stat) < 0)
- {
- err_str.SetError(errno, DNBError::POSIX);
- snprintf(err_msg, sizeof(err_msg), "%s: \"%s\"", err_str.AsString(), app_bundle_path);
- err_str.SetErrorString(err_msg);
- DNBLogThreadedIf(LOG_PROCESS, "%s() error: %s", __FUNCTION__, err_msg);
- }
- else
- {
- err_str.SetError(-1, DNBError::Generic);
- snprintf(err_msg, sizeof(err_msg), "failed to extract CFBundleIdentifier from %s", app_bundle_path);
- err_str.SetErrorString(err_msg);
- DNBLogThreadedIf(LOG_PROCESS, "%s() error: failed to extract CFBundleIdentifier from '%s'", __FUNCTION__, app_bundle_path);
- }
- return NULL;
+static CFStringRef CopyBundleIDForPath(const char *app_bundle_path,
+ DNBError &err_str) {
+ CFBundle bundle(app_bundle_path);
+ CFStringRef bundleIDCFStr = bundle.GetIdentifier();
+ std::string bundleID;
+ if (CFString::UTF8(bundleIDCFStr, bundleID) == NULL) {
+ struct stat app_bundle_stat;
+ char err_msg[PATH_MAX];
+
+ if (::stat(app_bundle_path, &app_bundle_stat) < 0) {
+ err_str.SetError(errno, DNBError::POSIX);
+ snprintf(err_msg, sizeof(err_msg), "%s: \"%s\"", err_str.AsString(),
+ app_bundle_path);
+ err_str.SetErrorString(err_msg);
+ DNBLogThreadedIf(LOG_PROCESS, "%s() error: %s", __FUNCTION__, err_msg);
+ } else {
+ err_str.SetError(-1, DNBError::Generic);
+ snprintf(err_msg, sizeof(err_msg),
+ "failed to extract CFBundleIdentifier from %s", app_bundle_path);
+ err_str.SetErrorString(err_msg);
+ DNBLogThreadedIf(
+ LOG_PROCESS,
+ "%s() error: failed to extract CFBundleIdentifier from '%s'",
+ __FUNCTION__, app_bundle_path);
}
+ return NULL;
+ }
- DNBLogThreadedIf(LOG_PROCESS, "%s() extracted CFBundleIdentifier: %s", __FUNCTION__, bundleID.c_str());
- CFRetain (bundleIDCFStr);
+ DNBLogThreadedIf(LOG_PROCESS, "%s() extracted CFBundleIdentifier: %s",
+ __FUNCTION__, bundleID.c_str());
+ CFRetain(bundleIDCFStr);
- return bundleIDCFStr;
+ return bundleIDCFStr;
}
-#endif // #if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS)
+#endif // #if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined
+ // (WITH_FBS)
#ifdef WITH_SPRINGBOARD
-pid_t
-MachProcess::SBLaunchForDebug (const char *path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, DNBError &launch_err)
-{
- // Clear out and clean up from any current state
- Clear();
-
- DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path);
-
- // Fork a child process for debugging
- SetState(eStateLaunching);
- m_pid = MachProcess::SBForkChildForPTraceDebugging(path, argv, envp, no_stdio, this, launch_err);
- if (m_pid != 0)
- {
- m_flags |= eMachProcessFlagsUsingSBS;
- m_path = path;
- size_t i;
- char const *arg;
- for (i=0; (arg = argv[i]) != NULL; i++)
- m_args.push_back(arg);
- m_task.StartExceptionThread(launch_err);
-
- if (launch_err.Fail())
- {
- if (launch_err.AsString() == NULL)
- launch_err.SetErrorString("unable to start the exception thread");
- DNBLog ("Could not get inferior's Mach exception port, sending ptrace PT_KILL and exiting.");
- ::ptrace (PT_KILL, m_pid, 0, 0);
- m_pid = INVALID_NUB_PROCESS;
- return INVALID_NUB_PROCESS;
- }
-
- StartSTDIOThread();
- SetState (eStateAttaching);
- int err = ::ptrace (PT_ATTACHEXC, m_pid, 0, 0);
- if (err == 0)
- {
- m_flags |= eMachProcessFlagsAttached;
- DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", m_pid);
- }
- else
- {
- SetState (eStateExited);
- DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", m_pid);
- }
+pid_t MachProcess::SBLaunchForDebug(const char *path, char const *argv[],
+ char const *envp[], bool no_stdio,
+ bool disable_aslr, DNBError &launch_err) {
+ // Clear out and clean up from any current state
+ Clear();
+
+ DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path);
+
+ // Fork a child process for debugging
+ SetState(eStateLaunching);
+ m_pid = MachProcess::SBForkChildForPTraceDebugging(path, argv, envp, no_stdio,
+ this, launch_err);
+ if (m_pid != 0) {
+ m_flags |= eMachProcessFlagsUsingSBS;
+ m_path = path;
+ size_t i;
+ char const *arg;
+ for (i = 0; (arg = argv[i]) != NULL; i++)
+ m_args.push_back(arg);
+ m_task.StartExceptionThread(launch_err);
+
+ if (launch_err.Fail()) {
+ if (launch_err.AsString() == NULL)
+ launch_err.SetErrorString("unable to start the exception thread");
+ DNBLog("Could not get inferior's Mach exception port, sending ptrace "
+ "PT_KILL and exiting.");
+ ::ptrace(PT_KILL, m_pid, 0, 0);
+ m_pid = INVALID_NUB_PROCESS;
+ return INVALID_NUB_PROCESS;
+ }
+
+ StartSTDIOThread();
+ SetState(eStateAttaching);
+ int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0);
+ if (err == 0) {
+ m_flags |= eMachProcessFlagsAttached;
+ DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", m_pid);
+ } else {
+ SetState(eStateExited);
+ DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", m_pid);
}
- return m_pid;
+ }
+ return m_pid;
}
#include <servers/bootstrap.h>
-pid_t
-MachProcess::SBForkChildForPTraceDebugging (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, MachProcess* process, DNBError &launch_err)
-{
- DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, app_bundle_path, process);
- CFAllocatorRef alloc = kCFAllocatorDefault;
-
- if (argv[0] == NULL)
- return INVALID_NUB_PROCESS;
-
- size_t argc = 0;
- // Count the number of arguments
- while (argv[argc] != NULL)
- argc++;
-
- // Enumerate the arguments
- size_t first_launch_arg_idx = 1;
- CFReleaser<CFMutableArrayRef> launch_argv;
-
- if (argv[first_launch_arg_idx])
- {
- size_t launch_argc = argc > 0 ? argc - 1 : 0;
- launch_argv.reset (::CFArrayCreateMutable (alloc, launch_argc, &kCFTypeArrayCallBacks));
- size_t i;
- char const *arg;
- CFString launch_arg;
- for (i=first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL); i++)
- {
- launch_arg.reset(::CFStringCreateWithCString (alloc, arg, kCFStringEncodingUTF8));
- if (launch_arg.get() != NULL)
- CFArrayAppendValue(launch_argv.get(), launch_arg.get());
- else
- break;
- }
- }
-
- // Next fill in the arguments dictionary. Note, the envp array is of the form
- // Variable=value but SpringBoard wants a CF dictionary. So we have to convert
- // this here.
-
- CFReleaser<CFMutableDictionaryRef> launch_envp;
-
- if (envp[0])
- {
- launch_envp.reset(::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
- const char *value;
- int name_len;
- CFString name_string, value_string;
-
- for (int i = 0; envp[i] != NULL; i++)
- {
- value = strstr (envp[i], "=");
-
- // If the name field is empty or there's no =, skip it. Somebody's messing with us.
- if (value == NULL || value == envp[i])
- continue;
-
- name_len = value - envp[i];
-
- // Now move value over the "="
- value++;
-
- name_string.reset(::CFStringCreateWithBytes(alloc, (const UInt8 *) envp[i], name_len, kCFStringEncodingUTF8, false));
- value_string.reset(::CFStringCreateWithCString(alloc, value, kCFStringEncodingUTF8));
- CFDictionarySetValue (launch_envp.get(), name_string.get(), value_string.get());
- }
- }
+pid_t MachProcess::SBForkChildForPTraceDebugging(
+ const char *app_bundle_path, char const *argv[], char const *envp[],
+ bool no_stdio, MachProcess *process, DNBError &launch_err) {
+ DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__,
+ app_bundle_path, process);
+ CFAllocatorRef alloc = kCFAllocatorDefault;
- CFString stdio_path;
+ if (argv[0] == NULL)
+ return INVALID_NUB_PROCESS;
- PseudoTerminal pty;
- if (!no_stdio)
- {
- PseudoTerminal::Error pty_err = pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY);
- if (pty_err == PseudoTerminal::success)
- {
- const char* slave_name = pty.SlaveName();
- DNBLogThreadedIf(LOG_PROCESS, "%s() successfully opened master pty, slave is %s", __FUNCTION__, slave_name);
- if (slave_name && slave_name[0])
- {
- ::chmod (slave_name, S_IRWXU | S_IRWXG | S_IRWXO);
- stdio_path.SetFileSystemRepresentation (slave_name);
- }
- }
+ size_t argc = 0;
+ // Count the number of arguments
+ while (argv[argc] != NULL)
+ argc++;
+
+ // Enumerate the arguments
+ size_t first_launch_arg_idx = 1;
+ CFReleaser<CFMutableArrayRef> launch_argv;
+
+ if (argv[first_launch_arg_idx]) {
+ size_t launch_argc = argc > 0 ? argc - 1 : 0;
+ launch_argv.reset(
+ ::CFArrayCreateMutable(alloc, launch_argc, &kCFTypeArrayCallBacks));
+ size_t i;
+ char const *arg;
+ CFString launch_arg;
+ for (i = first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL);
+ i++) {
+ launch_arg.reset(
+ ::CFStringCreateWithCString(alloc, arg, kCFStringEncodingUTF8));
+ if (launch_arg.get() != NULL)
+ CFArrayAppendValue(launch_argv.get(), launch_arg.get());
+ else
+ break;
}
-
- if (stdio_path.get() == NULL)
- {
- stdio_path.SetFileSystemRepresentation ("/dev/null");
- }
-
- CFStringRef bundleIDCFStr = CopyBundleIDForPath (app_bundle_path, launch_err);
- if (bundleIDCFStr == NULL)
- return INVALID_NUB_PROCESS;
-
- // This is just for logging:
- std::string bundleID;
- CFString::UTF8(bundleIDCFStr, bundleID);
+ }
- DNBLogThreadedIf(LOG_PROCESS, "%s() serialized launch arg array", __FUNCTION__);
+ // Next fill in the arguments dictionary. Note, the envp array is of the form
+ // Variable=value but SpringBoard wants a CF dictionary. So we have to
+ // convert
+ // this here.
+
+ CFReleaser<CFMutableDictionaryRef> launch_envp;
+
+ if (envp[0]) {
+ launch_envp.reset(
+ ::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ const char *value;
+ int name_len;
+ CFString name_string, value_string;
+
+ for (int i = 0; envp[i] != NULL; i++) {
+ value = strstr(envp[i], "=");
+
+ // If the name field is empty or there's no =, skip it. Somebody's
+ // messing with us.
+ if (value == NULL || value == envp[i])
+ continue;
+
+ name_len = value - envp[i];
+
+ // Now move value over the "="
+ value++;
+
+ name_string.reset(
+ ::CFStringCreateWithBytes(alloc, (const UInt8 *)envp[i], name_len,
+ kCFStringEncodingUTF8, false));
+ value_string.reset(
+ ::CFStringCreateWithCString(alloc, value, kCFStringEncodingUTF8));
+ CFDictionarySetValue(launch_envp.get(), name_string.get(),
+ value_string.get());
+ }
+ }
+
+ CFString stdio_path;
+
+ PseudoTerminal pty;
+ if (!no_stdio) {
+ PseudoTerminal::Error pty_err =
+ pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY);
+ if (pty_err == PseudoTerminal::success) {
+ const char *slave_name = pty.SlaveName();
+ DNBLogThreadedIf(LOG_PROCESS,
+ "%s() successfully opened master pty, slave is %s",
+ __FUNCTION__, slave_name);
+ if (slave_name && slave_name[0]) {
+ ::chmod(slave_name, S_IRWXU | S_IRWXG | S_IRWXO);
+ stdio_path.SetFileSystemRepresentation(slave_name);
+ }
+ }
+ }
+
+ if (stdio_path.get() == NULL) {
+ stdio_path.SetFileSystemRepresentation("/dev/null");
+ }
- // Find SpringBoard
- SBSApplicationLaunchError sbs_error = 0;
- sbs_error = SBSLaunchApplicationForDebugging (bundleIDCFStr,
- (CFURLRef)NULL, // openURL
- launch_argv.get(),
- launch_envp.get(), // CFDictionaryRef environment
- stdio_path.get(),
- stdio_path.get(),
- SBSApplicationLaunchWaitForDebugger | SBSApplicationLaunchUnlockDevice);
-
-
- launch_err.SetError(sbs_error, DNBError::SpringBoard);
-
- if (sbs_error == SBSApplicationLaunchErrorSuccess)
- {
- static const useconds_t pid_poll_interval = 200000;
- static const useconds_t pid_poll_timeout = 30000000;
-
- useconds_t pid_poll_total = 0;
-
- nub_process_t pid = INVALID_NUB_PROCESS;
- Boolean pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid);
- // Poll until the process is running, as long as we are getting valid responses and the timeout hasn't expired
- // A return PID of 0 means the process is not running, which may be because it hasn't been (asynchronously) started
- // yet, or that it died very quickly (if you weren't using waitForDebugger).
- while (!pid_found && pid_poll_total < pid_poll_timeout)
- {
- usleep (pid_poll_interval);
- pid_poll_total += pid_poll_interval;
- DNBLogThreadedIf(LOG_PROCESS, "%s() polling Springboard for pid for %s...", __FUNCTION__, bundleID.c_str());
- pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid);
- }
+ CFStringRef bundleIDCFStr = CopyBundleIDForPath(app_bundle_path, launch_err);
+ if (bundleIDCFStr == NULL)
+ return INVALID_NUB_PROCESS;
- CFRelease (bundleIDCFStr);
- if (pid_found)
- {
- if (process != NULL)
- {
- // Release our master pty file descriptor so the pty class doesn't
- // close it and so we can continue to use it in our STDIO thread
- int master_fd = pty.ReleaseMasterFD();
- process->SetChildFileDescriptors(master_fd, master_fd, master_fd);
- }
- DNBLogThreadedIf(LOG_PROCESS, "%s() => pid = %4.4x", __FUNCTION__, pid);
- }
- else
- {
- DNBLogError("failed to lookup the process ID for CFBundleIdentifier %s.", bundleID.c_str());
- }
- return pid;
+ // This is just for logging:
+ std::string bundleID;
+ CFString::UTF8(bundleIDCFStr, bundleID);
+
+ DNBLogThreadedIf(LOG_PROCESS, "%s() serialized launch arg array",
+ __FUNCTION__);
+
+ // Find SpringBoard
+ SBSApplicationLaunchError sbs_error = 0;
+ sbs_error = SBSLaunchApplicationForDebugging(
+ bundleIDCFStr,
+ (CFURLRef)NULL, // openURL
+ launch_argv.get(),
+ launch_envp.get(), // CFDictionaryRef environment
+ stdio_path.get(), stdio_path.get(),
+ SBSApplicationLaunchWaitForDebugger | SBSApplicationLaunchUnlockDevice);
+
+ launch_err.SetError(sbs_error, DNBError::SpringBoard);
+
+ if (sbs_error == SBSApplicationLaunchErrorSuccess) {
+ static const useconds_t pid_poll_interval = 200000;
+ static const useconds_t pid_poll_timeout = 30000000;
+
+ useconds_t pid_poll_total = 0;
+
+ nub_process_t pid = INVALID_NUB_PROCESS;
+ Boolean pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid);
+ // Poll until the process is running, as long as we are getting valid
+ // responses and the timeout hasn't expired
+ // A return PID of 0 means the process is not running, which may be because
+ // it hasn't been (asynchronously) started
+ // yet, or that it died very quickly (if you weren't using waitForDebugger).
+ while (!pid_found && pid_poll_total < pid_poll_timeout) {
+ usleep(pid_poll_interval);
+ pid_poll_total += pid_poll_interval;
+ DNBLogThreadedIf(LOG_PROCESS,
+ "%s() polling Springboard for pid for %s...",
+ __FUNCTION__, bundleID.c_str());
+ pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid);
+ }
+
+ CFRelease(bundleIDCFStr);
+ if (pid_found) {
+ if (process != NULL) {
+ // Release our master pty file descriptor so the pty class doesn't
+ // close it and so we can continue to use it in our STDIO thread
+ int master_fd = pty.ReleaseMasterFD();
+ process->SetChildFileDescriptors(master_fd, master_fd, master_fd);
+ }
+ DNBLogThreadedIf(LOG_PROCESS, "%s() => pid = %4.4x", __FUNCTION__, pid);
+ } else {
+ DNBLogError("failed to lookup the process ID for CFBundleIdentifier %s.",
+ bundleID.c_str());
}
+ return pid;
+ }
- DNBLogError("unable to launch the application with CFBundleIdentifier '%s' sbs_error = %u", bundleID.c_str(), sbs_error);
- return INVALID_NUB_PROCESS;
+ DNBLogError("unable to launch the application with CFBundleIdentifier '%s' "
+ "sbs_error = %u",
+ bundleID.c_str(), sbs_error);
+ return INVALID_NUB_PROCESS;
}
#endif // #ifdef WITH_SPRINGBOARD
-
+#if defined(WITH_BKS) || defined(WITH_FBS)
+pid_t MachProcess::BoardServiceLaunchForDebug(
+ const char *path, char const *argv[], char const *envp[], bool no_stdio,
+ bool disable_aslr, const char *event_data, DNBError &launch_err) {
+ DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path);
+
+ // Fork a child process for debugging
+ SetState(eStateLaunching);
+ m_pid = BoardServiceForkChildForPTraceDebugging(
+ path, argv, envp, no_stdio, disable_aslr, event_data, launch_err);
+ if (m_pid != 0) {
+ m_path = path;
+ size_t i;
+ char const *arg;
+ for (i = 0; (arg = argv[i]) != NULL; i++)
+ m_args.push_back(arg);
+ m_task.StartExceptionThread(launch_err);
+
+ if (launch_err.Fail()) {
+ if (launch_err.AsString() == NULL)
+ launch_err.SetErrorString("unable to start the exception thread");
+ DNBLog("Could not get inferior's Mach exception port, sending ptrace "
+ "PT_KILL and exiting.");
+ ::ptrace(PT_KILL, m_pid, 0, 0);
+ m_pid = INVALID_NUB_PROCESS;
+ return INVALID_NUB_PROCESS;
+ }
+
+ StartSTDIOThread();
+ SetState(eStateAttaching);
+ int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0);
+ if (err == 0) {
+ m_flags |= eMachProcessFlagsAttached;
+ DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", m_pid);
+ } else {
+ SetState(eStateExited);
+ DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", m_pid);
+ }
+ }
+ return m_pid;
+}
+
+pid_t MachProcess::BoardServiceForkChildForPTraceDebugging(
+ const char *app_bundle_path, char const *argv[], char const *envp[],
+ bool no_stdio, bool disable_aslr, const char *event_data,
+ DNBError &launch_err) {
+ if (argv[0] == NULL)
+ return INVALID_NUB_PROCESS;
-#if defined (WITH_BKS) || defined (WITH_FBS)
-pid_t
-MachProcess::BoardServiceLaunchForDebug (const char *path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err)
-{
- DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path);
-
- // Fork a child process for debugging
- SetState(eStateLaunching);
- m_pid = BoardServiceForkChildForPTraceDebugging(path, argv, envp, no_stdio, disable_aslr, event_data, launch_err);
- if (m_pid != 0)
- {
- m_path = path;
- size_t i;
- char const *arg;
- for (i=0; (arg = argv[i]) != NULL; i++)
- m_args.push_back(arg);
- m_task.StartExceptionThread(launch_err);
-
- if (launch_err.Fail())
- {
- if (launch_err.AsString() == NULL)
- launch_err.SetErrorString("unable to start the exception thread");
- DNBLog ("Could not get inferior's Mach exception port, sending ptrace PT_KILL and exiting.");
- ::ptrace (PT_KILL, m_pid, 0, 0);
- m_pid = INVALID_NUB_PROCESS;
- return INVALID_NUB_PROCESS;
- }
+ DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__,
+ app_bundle_path, this);
- StartSTDIOThread();
- SetState (eStateAttaching);
- int err = ::ptrace (PT_ATTACHEXC, m_pid, 0, 0);
- if (err == 0)
- {
- m_flags |= eMachProcessFlagsAttached;
- DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", m_pid);
- }
- else
- {
- SetState (eStateExited);
- DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", m_pid);
- }
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ size_t argc = 0;
+ // Count the number of arguments
+ while (argv[argc] != NULL)
+ argc++;
+
+ // Enumerate the arguments
+ size_t first_launch_arg_idx = 1;
+
+ NSMutableArray *launch_argv = nil;
+
+ if (argv[first_launch_arg_idx]) {
+ size_t launch_argc = argc > 0 ? argc - 1 : 0;
+ launch_argv = [NSMutableArray arrayWithCapacity:launch_argc];
+ size_t i;
+ char const *arg;
+ NSString *launch_arg;
+ for (i = first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL);
+ i++) {
+ launch_arg = [NSString stringWithUTF8String:arg];
+ // FIXME: Should we silently eat an argument that we can't convert into a
+ // UTF8 string?
+ if (launch_arg != nil)
+ [launch_argv addObject:launch_arg];
+ else
+ break;
}
- return m_pid;
-}
+ }
-pid_t
-MachProcess::BoardServiceForkChildForPTraceDebugging (const char *app_bundle_path,
- char const *argv[],
- char const *envp[],
- bool no_stdio,
- bool disable_aslr,
- const char *event_data,
- DNBError &launch_err)
-{
- if (argv[0] == NULL)
- return INVALID_NUB_PROCESS;
+ NSMutableDictionary *launch_envp = nil;
+ if (envp[0]) {
+ launch_envp = [[NSMutableDictionary alloc] init];
+ const char *value;
+ int name_len;
+ NSString *name_string, *value_string;
+
+ for (int i = 0; envp[i] != NULL; i++) {
+ value = strstr(envp[i], "=");
+
+ // If the name field is empty or there's no =, skip it. Somebody's
+ // messing with us.
+ if (value == NULL || value == envp[i])
+ continue;
+
+ name_len = value - envp[i];
+
+ // Now move value over the "="
+ value++;
+ name_string = [[NSString alloc] initWithBytes:envp[i]
+ length:name_len
+ encoding:NSUTF8StringEncoding];
+ value_string = [NSString stringWithUTF8String:value];
+ [launch_envp setObject:value_string forKey:name_string];
+ }
+ }
+
+ NSString *stdio_path = nil;
+ NSFileManager *file_manager = [NSFileManager defaultManager];
+
+ PseudoTerminal pty;
+ if (!no_stdio) {
+ PseudoTerminal::Error pty_err =
+ pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY);
+ if (pty_err == PseudoTerminal::success) {
+ const char *slave_name = pty.SlaveName();
+ DNBLogThreadedIf(LOG_PROCESS,
+ "%s() successfully opened master pty, slave is %s",
+ __FUNCTION__, slave_name);
+ if (slave_name && slave_name[0]) {
+ ::chmod(slave_name, S_IRWXU | S_IRWXG | S_IRWXO);
+ stdio_path = [file_manager
+ stringWithFileSystemRepresentation:slave_name
+ length:strlen(slave_name)];
+ }
+ }
+ }
+
+ if (stdio_path == nil) {
+ const char *null_path = "/dev/null";
+ stdio_path =
+ [file_manager stringWithFileSystemRepresentation:null_path
+ length:strlen(null_path)];
+ }
- DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, app_bundle_path, this);
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ CFStringRef bundleIDCFStr = CopyBundleIDForPath(app_bundle_path, launch_err);
+ if (bundleIDCFStr == NULL) {
+ [pool drain];
+ return INVALID_NUB_PROCESS;
+ }
- size_t argc = 0;
- // Count the number of arguments
- while (argv[argc] != NULL)
- argc++;
-
- // Enumerate the arguments
- size_t first_launch_arg_idx = 1;
-
- NSMutableArray *launch_argv = nil;
-
- if (argv[first_launch_arg_idx])
- {
- size_t launch_argc = argc > 0 ? argc - 1 : 0;
- launch_argv = [NSMutableArray arrayWithCapacity: launch_argc];
- size_t i;
- char const *arg;
- NSString *launch_arg;
- for (i=first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL); i++)
- {
- launch_arg = [NSString stringWithUTF8String: arg];
- // FIXME: Should we silently eat an argument that we can't convert into a UTF8 string?
- if (launch_arg != nil)
- [launch_argv addObject: launch_arg];
- else
- break;
- }
- }
+ // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use
+ // toll-free bridging here:
+ NSString *bundleIDNSStr = (NSString *)bundleIDCFStr;
+
+ // Okay, now let's assemble all these goodies into the BackBoardServices
+ // options mega-dictionary:
+
+ NSMutableDictionary *options = nullptr;
+ pid_t return_pid = INVALID_NUB_PROCESS;
+ bool success = false;
- NSMutableDictionary *launch_envp = nil;
- if (envp[0])
- {
- launch_envp = [[NSMutableDictionary alloc] init];
- const char *value;
- int name_len;
- NSString *name_string, *value_string;
-
- for (int i = 0; envp[i] != NULL; i++)
- {
- value = strstr (envp[i], "=");
-
- // If the name field is empty or there's no =, skip it. Somebody's messing with us.
- if (value == NULL || value == envp[i])
- continue;
-
- name_len = value - envp[i];
-
- // Now move value over the "="
- value++;
- name_string = [[NSString alloc] initWithBytes: envp[i] length: name_len encoding: NSUTF8StringEncoding];
- value_string = [NSString stringWithUTF8String: value];
- [launch_envp setObject: value_string forKey: name_string];
- }
- }
+#ifdef WITH_BKS
+ if (m_flags & eMachProcessFlagsUsingBKS) {
+ options =
+ BKSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp,
+ stdio_path, disable_aslr, event_data);
+ success = BKSCallOpenApplicationFunction(bundleIDNSStr, options, launch_err,
+ &return_pid);
+ }
+#endif
+#ifdef WITH_FBS
+ if (m_flags & eMachProcessFlagsUsingFBS) {
+ options =
+ FBSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp,
+ stdio_path, disable_aslr, event_data);
+ success = FBSCallOpenApplicationFunction(bundleIDNSStr, options, launch_err,
+ &return_pid);
+ }
+#endif
- NSString *stdio_path = nil;
- NSFileManager *file_manager = [NSFileManager defaultManager];
+ if (success) {
+ int master_fd = pty.ReleaseMasterFD();
+ SetChildFileDescriptors(master_fd, master_fd, master_fd);
+ CFString::UTF8(bundleIDCFStr, m_bundle_id);
+ }
- PseudoTerminal pty;
- if (!no_stdio)
- {
- PseudoTerminal::Error pty_err = pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY);
- if (pty_err == PseudoTerminal::success)
- {
- const char* slave_name = pty.SlaveName();
- DNBLogThreadedIf(LOG_PROCESS, "%s() successfully opened master pty, slave is %s", __FUNCTION__, slave_name);
- if (slave_name && slave_name[0])
- {
- ::chmod (slave_name, S_IRWXU | S_IRWXG | S_IRWXO);
- stdio_path = [file_manager stringWithFileSystemRepresentation: slave_name length: strlen(slave_name)];
- }
- }
- }
-
- if (stdio_path == nil)
- {
- const char *null_path = "/dev/null";
- stdio_path = [file_manager stringWithFileSystemRepresentation: null_path length: strlen(null_path)];
- }
-
- CFStringRef bundleIDCFStr = CopyBundleIDForPath (app_bundle_path, launch_err);
- if (bundleIDCFStr == NULL)
- {
- [pool drain];
- return INVALID_NUB_PROCESS;
- }
+ [pool drain];
+
+ return return_pid;
+}
- // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use toll-free bridging here:
- NSString *bundleIDNSStr = (NSString *) bundleIDCFStr;
+bool MachProcess::BoardServiceSendEvent(const char *event_data,
+ DNBError &send_err) {
+ bool return_value = true;
- // Okay, now let's assemble all these goodies into the BackBoardServices options mega-dictionary:
-
- NSMutableDictionary *options = nullptr;
- pid_t return_pid = INVALID_NUB_PROCESS;
- bool success = false;
+ if (event_data == NULL || *event_data == '\0') {
+ DNBLogError("SendEvent called with NULL event data.");
+ send_err.SetErrorString("SendEvent called with empty event data");
+ return false;
+ }
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ if (strcmp(event_data, "BackgroundApplication") == 0) {
+// This is an event I cooked up. What you actually do is foreground the system
+// app, so:
#ifdef WITH_BKS
- if (m_flags & eMachProcessFlagsUsingBKS)
- {
- options = BKSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp, stdio_path, disable_aslr, event_data);
- success = BKSCallOpenApplicationFunction (bundleIDNSStr, options, launch_err, &return_pid);
- }
+ if (m_flags & eMachProcessFlagsUsingBKS) {
+ return_value = BKSCallOpenApplicationFunction(nil, nil, send_err, NULL);
+ }
#endif
#ifdef WITH_FBS
- if (m_flags & eMachProcessFlagsUsingFBS)
- {
- options = FBSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp, stdio_path, disable_aslr, event_data);
- success = FBSCallOpenApplicationFunction (bundleIDNSStr, options, launch_err, &return_pid);
+ if (m_flags & eMachProcessFlagsUsingFBS) {
+ return_value = FBSCallOpenApplicationFunction(nil, nil, send_err, NULL);
}
#endif
-
- if (success)
- {
- int master_fd = pty.ReleaseMasterFD();
- SetChildFileDescriptors(master_fd, master_fd, master_fd);
- CFString::UTF8(bundleIDCFStr, m_bundle_id);
+ if (!return_value) {
+ DNBLogError("Failed to background application, error: %s.",
+ send_err.AsString());
}
-
- [pool drain];
+ } else {
+ if (m_bundle_id.empty()) {
+ // See if we can figure out the bundle ID for this PID:
- return return_pid;
-}
+ DNBLogError(
+ "Tried to send event \"%s\" to a process that has no bundle ID.",
+ event_data);
+ return false;
+ }
+
+ NSString *bundleIDNSStr =
+ [NSString stringWithUTF8String:m_bundle_id.c_str()];
-bool
-MachProcess::BoardServiceSendEvent (const char *event_data, DNBError &send_err)
-{
- bool return_value = true;
-
- if (event_data == NULL || *event_data == '\0')
- {
- DNBLogError ("SendEvent called with NULL event data.");
- send_err.SetErrorString("SendEvent called with empty event data");
+ NSMutableDictionary *options = [NSMutableDictionary dictionary];
+
+#ifdef WITH_BKS
+ if (m_flags & eMachProcessFlagsUsingBKS) {
+ if (!BKSAddEventDataToOptions(options, event_data, send_err)) {
+ [pool drain];
return false;
+ }
+ return_value = BKSCallOpenApplicationFunction(bundleIDNSStr, options,
+ send_err, NULL);
+ DNBLogThreadedIf(LOG_PROCESS,
+ "Called BKSCallOpenApplicationFunction to send event.");
}
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- if (strcmp (event_data, "BackgroundApplication") == 0)
- {
- // This is an event I cooked up. What you actually do is foreground the system app, so:
-#ifdef WITH_BKS
- if (m_flags & eMachProcessFlagsUsingBKS)
- {
- return_value = BKSCallOpenApplicationFunction(nil, nil, send_err, NULL);
- }
#endif
#ifdef WITH_FBS
- if (m_flags & eMachProcessFlagsUsingFBS)
- {
- return_value = FBSCallOpenApplicationFunction(nil, nil, send_err, NULL);
- }
-#endif
- if (!return_value)
- {
- DNBLogError ("Failed to background application, error: %s.", send_err.AsString());
- }
+ if (m_flags & eMachProcessFlagsUsingFBS) {
+ if (!FBSAddEventDataToOptions(options, event_data, send_err)) {
+ [pool drain];
+ return false;
+ }
+ return_value = FBSCallOpenApplicationFunction(bundleIDNSStr, options,
+ send_err, NULL);
+ DNBLogThreadedIf(LOG_PROCESS,
+ "Called FBSCallOpenApplicationFunction to send event.");
}
- else
- {
- if (m_bundle_id.empty())
- {
- // See if we can figure out the bundle ID for this PID:
-
- DNBLogError ("Tried to send event \"%s\" to a process that has no bundle ID.", event_data);
- return false;
- }
-
- NSString *bundleIDNSStr = [NSString stringWithUTF8String:m_bundle_id.c_str()];
-
- NSMutableDictionary *options = [NSMutableDictionary dictionary];
-
-#ifdef WITH_BKS
- if (m_flags & eMachProcessFlagsUsingBKS)
- {
- if (!BKSAddEventDataToOptions(options, event_data, send_err))
- {
- [pool drain];
- return false;
- }
- return_value = BKSCallOpenApplicationFunction (bundleIDNSStr, options, send_err, NULL);
- DNBLogThreadedIf (LOG_PROCESS, "Called BKSCallOpenApplicationFunction to send event.");
-
- }
#endif
-#ifdef WITH_FBS
- if (m_flags & eMachProcessFlagsUsingFBS)
- {
- if (!FBSAddEventDataToOptions(options, event_data, send_err))
- {
- [pool drain];
- return false;
- }
- return_value = FBSCallOpenApplicationFunction (bundleIDNSStr, options, send_err, NULL);
- DNBLogThreadedIf (LOG_PROCESS, "Called FBSCallOpenApplicationFunction to send event.");
- }
-#endif
-
- if (!return_value)
- {
- DNBLogError ("Failed to send event: %s, error: %s.", event_data, send_err.AsString());
- }
+
+ if (!return_value) {
+ DNBLogError("Failed to send event: %s, error: %s.", event_data,
+ send_err.AsString());
}
-
- [pool drain];
- return return_value;
+ }
+
+ [pool drain];
+ return return_value;
}
#endif // defined(WITH_BKS) || defined (WITH_FBS)
#ifdef WITH_BKS
-void
-MachProcess::BKSCleanupAfterAttach (const void *attach_token, DNBError &err_str)
-{
- bool success;
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use toll-free bridging here:
- NSString *bundleIDNSStr = (NSString *) attach_token;
-
- // Okay, now let's assemble all these goodies into the BackBoardServices options mega-dictionary:
-
- // First we have the debug sub-dictionary:
- NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
- [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyCancelDebugOnNextLaunch];
-
- // That will go in the overall dictionary:
-
- NSMutableDictionary *options = [NSMutableDictionary dictionary];
- [options setObject: debug_options forKey: BKSOpenApplicationOptionKeyDebuggingOptions];
+void MachProcess::BKSCleanupAfterAttach(const void *attach_token,
+ DNBError &err_str) {
+ bool success;
- success = BKSCallOpenApplicationFunction (bundleIDNSStr, options, err_str, NULL);
-
- if (!success)
- {
- DNBLogError ("error trying to cancel debug on next launch for %s: %s", [bundleIDNSStr UTF8String], err_str.AsString());
- }
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [pool drain];
+ // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use
+ // toll-free bridging here:
+ NSString *bundleIDNSStr = (NSString *)attach_token;
+
+ // Okay, now let's assemble all these goodies into the BackBoardServices
+ // options mega-dictionary:
+
+ // First we have the debug sub-dictionary:
+ NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+ [debug_options setObject:[NSNumber numberWithBool:YES]
+ forKey:BKSDebugOptionKeyCancelDebugOnNextLaunch];
+
+ // That will go in the overall dictionary:
+
+ NSMutableDictionary *options = [NSMutableDictionary dictionary];
+ [options setObject:debug_options
+ forKey:BKSOpenApplicationOptionKeyDebuggingOptions];
+
+ success =
+ BKSCallOpenApplicationFunction(bundleIDNSStr, options, err_str, NULL);
+
+ if (!success) {
+ DNBLogError("error trying to cancel debug on next launch for %s: %s",
+ [bundleIDNSStr UTF8String], err_str.AsString());
+ }
+
+ [pool drain];
}
#endif // WITH_BKS
#ifdef WITH_FBS
-void
-MachProcess::FBSCleanupAfterAttach (const void *attach_token, DNBError &err_str)
-{
- bool success;
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use toll-free bridging here:
- NSString *bundleIDNSStr = (NSString *) attach_token;
-
- // Okay, now let's assemble all these goodies into the BackBoardServices options mega-dictionary:
-
- // First we have the debug sub-dictionary:
- NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
- [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyCancelDebugOnNextLaunch];
-
- // That will go in the overall dictionary:
-
- NSMutableDictionary *options = [NSMutableDictionary dictionary];
- [options setObject: debug_options forKey: FBSOpenApplicationOptionKeyDebuggingOptions];
+void MachProcess::FBSCleanupAfterAttach(const void *attach_token,
+ DNBError &err_str) {
+ bool success;
- success = FBSCallOpenApplicationFunction (bundleIDNSStr, options, err_str, NULL);
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- if (!success)
- {
- DNBLogError ("error trying to cancel debug on next launch for %s: %s", [bundleIDNSStr UTF8String], err_str.AsString());
- }
+ // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use
+ // toll-free bridging here:
+ NSString *bundleIDNSStr = (NSString *)attach_token;
- [pool drain];
+ // Okay, now let's assemble all these goodies into the BackBoardServices
+ // options mega-dictionary:
+
+ // First we have the debug sub-dictionary:
+ NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+ [debug_options setObject:[NSNumber numberWithBool:YES]
+ forKey:FBSDebugOptionKeyCancelDebugOnNextLaunch];
+
+ // That will go in the overall dictionary:
+
+ NSMutableDictionary *options = [NSMutableDictionary dictionary];
+ [options setObject:debug_options
+ forKey:FBSOpenApplicationOptionKeyDebuggingOptions];
+
+ success =
+ FBSCallOpenApplicationFunction(bundleIDNSStr, options, err_str, NULL);
+
+ if (!success) {
+ DNBLogError("error trying to cancel debug on next launch for %s: %s",
+ [bundleIDNSStr UTF8String], err_str.AsString());
+ }
+
+ [pool drain];
}
#endif // WITH_FBS
Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachTask.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachTask.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachTask.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachTask.h Tue Sep 6 15:57:50 2016
@@ -35,80 +35,82 @@ class MachProcess;
typedef uint64_t MachMallocEventId;
-enum MachMallocEventType
-{
- eMachMallocEventTypeAlloc = 2,
- eMachMallocEventTypeDealloc = 4,
- eMachMallocEventTypeOther = 1
+enum MachMallocEventType {
+ eMachMallocEventTypeAlloc = 2,
+ eMachMallocEventTypeDealloc = 4,
+ eMachMallocEventTypeOther = 1
};
-struct MachMallocEvent
-{
- mach_vm_address_t m_base_address;
- uint64_t m_size;
- MachMallocEventType m_event_type;
- MachMallocEventId m_event_id;
+struct MachMallocEvent {
+ mach_vm_address_t m_base_address;
+ uint64_t m_size;
+ MachMallocEventType m_event_type;
+ MachMallocEventId m_event_id;
};
-class MachTask
-{
+class MachTask {
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- MachTask (MachProcess *process);
- virtual ~MachTask ();
-
- void Clear ();
-
- kern_return_t Suspend ();
- kern_return_t Resume ();
-
- nub_size_t ReadMemory (nub_addr_t addr, nub_size_t size, void *buf);
- nub_size_t WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf);
- int GetMemoryRegionInfo (nub_addr_t addr, DNBRegionInfo *region_info);
- std::string GetProfileData (DNBProfileDataScanType scanType);
-
- nub_addr_t AllocateMemory (nub_size_t size, uint32_t permissions);
- nub_bool_t DeallocateMemory (nub_addr_t addr);
-
- mach_port_t ExceptionPort () const;
- bool ExceptionPortIsValid () const;
- kern_return_t SaveExceptionPortInfo ();
- kern_return_t RestoreExceptionPortInfo ();
- kern_return_t ShutDownExcecptionThread ();
-
- bool StartExceptionThread (DNBError &err);
- nub_addr_t GetDYLDAllImageInfosAddress (DNBError& err);
- kern_return_t BasicInfo (struct task_basic_info *info);
- static kern_return_t BasicInfo (task_t task, struct task_basic_info *info);
- bool IsValid () const;
- static bool IsValid (task_t task);
- static void * ExceptionThread (void *arg);
- task_t TaskPort () const { return m_task; }
- task_t TaskPortForProcessID (DNBError &err, bool force = false);
- static task_t TaskPortForProcessID (pid_t pid, DNBError &err, uint32_t num_retries = 10, uint32_t usec_interval = 10000);
-
- MachProcess * Process () { return m_process; }
- const MachProcess * Process () const { return m_process; }
-
- nub_size_t PageSize ();
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ MachTask(MachProcess *process);
+ virtual ~MachTask();
+
+ void Clear();
+
+ kern_return_t Suspend();
+ kern_return_t Resume();
+
+ nub_size_t ReadMemory(nub_addr_t addr, nub_size_t size, void *buf);
+ nub_size_t WriteMemory(nub_addr_t addr, nub_size_t size, const void *buf);
+ int GetMemoryRegionInfo(nub_addr_t addr, DNBRegionInfo *region_info);
+ std::string GetProfileData(DNBProfileDataScanType scanType);
+
+ nub_addr_t AllocateMemory(nub_size_t size, uint32_t permissions);
+ nub_bool_t DeallocateMemory(nub_addr_t addr);
+
+ mach_port_t ExceptionPort() const;
+ bool ExceptionPortIsValid() const;
+ kern_return_t SaveExceptionPortInfo();
+ kern_return_t RestoreExceptionPortInfo();
+ kern_return_t ShutDownExcecptionThread();
+
+ bool StartExceptionThread(DNBError &err);
+ nub_addr_t GetDYLDAllImageInfosAddress(DNBError &err);
+ kern_return_t BasicInfo(struct task_basic_info *info);
+ static kern_return_t BasicInfo(task_t task, struct task_basic_info *info);
+ bool IsValid() const;
+ static bool IsValid(task_t task);
+ static void *ExceptionThread(void *arg);
+ task_t TaskPort() const { return m_task; }
+ task_t TaskPortForProcessID(DNBError &err, bool force = false);
+ static task_t TaskPortForProcessID(pid_t pid, DNBError &err,
+ uint32_t num_retries = 10,
+ uint32_t usec_interval = 10000);
+
+ MachProcess *Process() { return m_process; }
+ const MachProcess *Process() const { return m_process; }
+
+ nub_size_t PageSize();
protected:
- MachProcess * m_process; // The mach process that owns this MachTask
- task_t m_task;
- MachVMMemory m_vm_memory; // Special mach memory reading class that will take care of watching for page and region boundaries
- MachException::PortInfo
- m_exc_port_info; // Saved settings for all exception ports
- pthread_t m_exception_thread; // Thread ID for the exception thread in case we need it
- mach_port_t m_exception_port; // Exception port on which we will receive child exceptions
+ MachProcess *m_process; // The mach process that owns this MachTask
+ task_t m_task;
+ MachVMMemory m_vm_memory; // Special mach memory reading class that will take
+ // care of watching for page and region boundaries
+ MachException::PortInfo
+ m_exc_port_info; // Saved settings for all exception ports
+ pthread_t m_exception_thread; // Thread ID for the exception thread in case we
+ // need it
+ mach_port_t m_exception_port; // Exception port on which we will receive child
+ // exceptions
- typedef std::map <mach_vm_address_t, size_t> allocation_collection;
- allocation_collection m_allocations;
+ typedef std::map<mach_vm_address_t, size_t> allocation_collection;
+ allocation_collection m_allocations;
private:
- MachTask(const MachTask&); // Outlaw
- MachTask& operator=(const MachTask& rhs);// Outlaw
+ MachTask(const MachTask &); // Outlaw
+ MachTask &operator=(const MachTask &rhs); // Outlaw
};
-#endif // __MachTask_h__
+#endif // __MachTask_h__
More information about the lldb-commits
mailing list