summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Darwin
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Darwin')
-rw-r--r--lldb/source/Plugins/Process/Darwin/CFBundle.cpp90
-rw-r--r--lldb/source/Plugins/Process/Darwin/CFBundle.h31
-rw-r--r--lldb/source/Plugins/Process/Darwin/CFString.cpp232
-rw-r--r--lldb/source/Plugins/Process/Darwin/CFString.h38
-rw-r--r--lldb/source/Plugins/Process/Darwin/CFUtils.h91
-rw-r--r--lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp1185
-rw-r--r--lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.h11
-rw-r--r--lldb/source/Plugins/Process/Darwin/LaunchFlavor.h19
-rw-r--r--lldb/source/Plugins/Process/Darwin/MachException.cpp967
-rw-r--r--lldb/source/Plugins/Process/Darwin/MachException.h239
-rw-r--r--lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp2795
-rw-r--r--lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h603
-rw-r--r--lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp264
-rw-r--r--lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.h200
-rw-r--r--lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp399
-rw-r--r--lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.h113
16 files changed, 3230 insertions, 4047 deletions
diff --git a/lldb/source/Plugins/Process/Darwin/CFBundle.cpp b/lldb/source/Plugins/Process/Darwin/CFBundle.cpp
index fdcb7cc2fcb..7b080e60cdb 100644
--- a/lldb/source/Plugins/Process/Darwin/CFBundle.cpp
+++ b/lldb/source/Plugins/Process/Darwin/CFBundle.cpp
@@ -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;
+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;
+CFURLRef CFBundle::CopyExecutableURL() const {
+ CFBundleRef bundle = get();
+ if (bundle != NULL)
+ return CFBundleCopyExecutableURL(bundle);
+ return NULL;
}
diff --git a/lldb/source/Plugins/Process/Darwin/CFBundle.h b/lldb/source/Plugins/Process/Darwin/CFBundle.h
index e08290add73..09957af534b 100644
--- a/lldb/source/Plugins/Process/Darwin/CFBundle.h
+++ b/lldb/source/Plugins/Process/Darwin/CFBundle.h
@@ -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);
+ //------------------------------------------------------------------
+ // 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;
+ CFStringRef GetIdentifier() const;
+
+ CFURLRef CopyExecutableURL() const;
- CFURLRef
- CopyExecutableURL () const;
-
protected:
- CFReleaser<CFURLRef> m_bundle_url;
+ CFReleaser<CFURLRef> m_bundle_url;
};
#endif // #ifndef __CFBundle_h__
diff --git a/lldb/source/Plugins/Process/Darwin/CFString.cpp b/lldb/source/Plugins/Process/Darwin/CFString.cpp
index 819024ca3bc..84ad56774d7 100644
--- a/lldb/source/Plugins/Process/Darwin/CFString.cpp
+++ b/lldb/source/Plugins/Process/Darwin/CFString.cpp
@@ -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::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::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::string& str)
// 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;
+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();
-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();
+ return expanded_path.c_str();
}
-
diff --git a/lldb/source/Plugins/Process/Darwin/CFString.h b/lldb/source/Plugins/Process/Darwin/CFString.h
index 73945a28a65..18d60a5a74b 100644
--- a/lldb/source/Plugins/Process/Darwin/CFString.h
+++ b/lldb/source/Plugins/Process/Darwin/CFString.h
@@ -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__
diff --git a/lldb/source/Plugins/Process/Darwin/CFUtils.h b/lldb/source/Plugins/Process/Darwin/CFUtils.h
index afa984fa11c..a904cd0ea6f 100644
--- a/lldb/source/Plugins/Process/Darwin/CFUtils.h
+++ b/lldb/source/Plugins/Process/Darwin/CFUtils.h
@@ -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(); }
+ // 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; }
+ // 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; }
+ // 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;
- }
- }
+ // 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__
diff --git a/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp b/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
index 91abe4f26e2..408f0abe72d 100644
--- a/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
+++ b/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
@@ -15,7 +15,7 @@
#include <sys/sysctl.h>
#ifndef _POSIX_SPAWN_DISABLE_ASLR
-#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
+#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
#endif
// LLDB includes
@@ -35,703 +35,610 @@ using namespace lldb_private;
using namespace lldb_private::process_darwin;
using namespace lldb_private::darwin_process_launcher;
-namespace
-{
- static LaunchFlavor g_launch_flavor = LaunchFlavor::Default;
+namespace {
+static LaunchFlavor g_launch_flavor = LaunchFlavor::Default;
}
-namespace lldb_private
-{
-namespace darwin_process_launcher
-{
-
-static uint32_t
-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;
+namespace lldb_private {
+namespace darwin_process_launcher {
+
+static uint32_t 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;
}
-static bool
-ResolveExecutablePath(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;
- }
- }
- }
+static bool ResolveExecutablePath(const char *path, char *resolved_path,
+ size_t resolved_path_size) {
+ if (path == NULL || path[0] == '\0')
+ return false;
- 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;
+ 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;
+ }
}
- 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;
- }
- }
+ }
+
+ 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;
+ }
+ return false;
}
// TODO check if we have a general purpose fork and exec. We may be
// able to get rid of this entirely.
-static Error
-ForkChildForPTraceDebugging(const char *path,
- char const *argv[],
- char const *envp[],
- ::pid_t *pid,
- int *pty_fd)
-{
- Error error;
- if (!path || !argv || !envp || !pid || !pty_fd)
- {
- error.SetErrorString("invalid arguments");
- return error;
- }
-
- // 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.
- lldb_utility::PseudoTerminal pty;
- char fork_error[256];
- memset(fork_error, 0, sizeof(fork_error));
- *pid = static_cast<::pid_t>(pty.Fork(fork_error, sizeof(fork_error)));
- if (*pid < 0)
- {
- //--------------------------------------------------------------
- // Error during fork.
- //--------------------------------------------------------------
- *pid = static_cast<::pid_t>(LLDB_INVALID_PROCESS_ID);
- error.SetErrorStringWithFormat("%s(): fork failed: %s",
- __FUNCTION__, fork_error);
- return error;
- }
- else if (pid == 0)
- {
- //--------------------------------------------------------------
- // Child process
- //--------------------------------------------------------------
-
- // Debug this process.
- ::ptrace(PT_TRACE_ME, 0, 0, 0);
-
- // Get BSD signals as mach exceptions.
- ::ptrace(PT_SIGEXC, 0, 0, 0);
-
- // 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.
-
- // Set the child process group to match its pid.
- ::setpgid(0, 0);
-
- // Sleep a bit to before the exec call.
- ::sleep(1);
-
- // Turn this process into the given executable.
- ::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.
-
- // Set the child process group to match its pid
- ::setpgid(*pid, *pid);
- if (pty_fd)
- {
- // 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
- *pty_fd = pty.ReleaseMasterFileDescriptor();
- }
- }
+static Error ForkChildForPTraceDebugging(const char *path, char const *argv[],
+ char const *envp[], ::pid_t *pid,
+ int *pty_fd) {
+ Error error;
+ if (!path || !argv || !envp || !pid || !pty_fd) {
+ error.SetErrorString("invalid arguments");
return error;
-}
+ }
+
+ // 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.
+ lldb_utility::PseudoTerminal pty;
+ char fork_error[256];
+ memset(fork_error, 0, sizeof(fork_error));
+ *pid = static_cast<::pid_t>(pty.Fork(fork_error, sizeof(fork_error)));
+ if (*pid < 0) {
+ //--------------------------------------------------------------
+ // Error during fork.
+ //--------------------------------------------------------------
+ *pid = static_cast<::pid_t>(LLDB_INVALID_PROCESS_ID);
+ error.SetErrorStringWithFormat("%s(): fork failed: %s", __FUNCTION__,
+ fork_error);
+ return error;
+ } else if (pid == 0) {
+ //--------------------------------------------------------------
+ // Child process
+ //--------------------------------------------------------------
-static Error
-CreatePosixSpawnFileAction(const FileAction &action,
- posix_spawn_file_actions_t *file_actions)
-{
- Error error;
+ // Debug this process.
+ ::ptrace(PT_TRACE_ME, 0, 0, 0);
- // Log it.
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- {
- StreamString stream;
- stream.PutCString("converting file action for posix_spawn(): ");
- action.Dump(stream);
- stream.Flush();
- log->PutCString(stream.GetString().c_str());
- }
+ // Get BSD signals as mach exceptions.
+ ::ptrace(PT_SIGEXC, 0, 0, 0);
- // Validate args.
- if (!file_actions)
- {
- error.SetErrorString("mandatory file_actions arg is null");
- return error;
- }
+ // 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.
- // Build the posix file action.
- switch (action.GetAction())
- {
- case FileAction::eFileActionOpen:
- {
- const int error_code =
- ::posix_spawn_file_actions_addopen(file_actions,
- action.GetFD(),
- action.GetPath(),
- action.GetActionArgument(),
- 0);
- if (error_code != 0)
- {
- error.SetError(error_code, eErrorTypePOSIX);
- return error;
- }
- break;
- }
+ // Set the child process group to match its pid.
+ ::setpgid(0, 0);
- case FileAction::eFileActionClose:
- {
- const int error_code =
- ::posix_spawn_file_actions_addclose(file_actions,
- action.GetFD());
- if (error_code != 0)
- {
- error.SetError(error_code, eErrorTypePOSIX);
- return error;
- }
- break;
- }
-
- case FileAction::eFileActionDuplicate:
- {
- const int error_code =
- ::posix_spawn_file_actions_adddup2(file_actions,
- action.GetFD(),
- action.GetActionArgument());
- if (error_code != 0)
- {
- error.SetError(error_code, eErrorTypePOSIX);
- return error;
- }
- break;
- }
+ // Sleep a bit to before the exec call.
+ ::sleep(1);
- case FileAction::eFileActionNone:
- default:
- if (log)
- log->Printf("%s(): unsupported file action %u",
- __FUNCTION__, action.GetAction());
- break;
+ // Turn this process into the given executable.
+ ::execv(path, (char *const *)argv);
}
-
- return error;
+ // 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.
+
+ // Set the child process group to match its pid
+ ::setpgid(*pid, *pid);
+ if (pty_fd) {
+ // 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
+ *pty_fd = pty.ReleaseMasterFileDescriptor();
+ }
+ }
+ return error;
}
static Error
-PosixSpawnChildForPTraceDebugging(const char *path,
- ProcessLaunchInfo &launch_info,
- ::pid_t *pid,
- cpu_type_t *actual_cpu_type)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- if (!pid)
- {
- error.SetErrorStringWithFormat("%s(): pid arg cannot be null",
- __FUNCTION__);
- return error;
+CreatePosixSpawnFileAction(const FileAction &action,
+ posix_spawn_file_actions_t *file_actions) {
+ Error error;
+
+ // Log it.
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log) {
+ StreamString stream;
+ stream.PutCString("converting file action for posix_spawn(): ");
+ action.Dump(stream);
+ stream.Flush();
+ log->PutCString(stream.GetString().c_str());
+ }
+
+ // Validate args.
+ if (!file_actions) {
+ error.SetErrorString("mandatory file_actions arg is null");
+ return error;
+ }
+
+ // Build the posix file action.
+ switch (action.GetAction()) {
+ case FileAction::eFileActionOpen: {
+ const int error_code = ::posix_spawn_file_actions_addopen(
+ file_actions, action.GetFD(), action.GetPath(),
+ action.GetActionArgument(), 0);
+ if (error_code != 0) {
+ error.SetError(error_code, eErrorTypePOSIX);
+ return error;
}
-
- posix_spawnattr_t attr;
- short flags;
- if (log)
- {
- StreamString stream;
- stream.Printf("%s(path='%s',...)\n", __FUNCTION__, path);
- launch_info.Dump(stream, nullptr);
- stream.Flush();
- log->PutCString(stream.GetString().c_str());
+ break;
+ }
+
+ case FileAction::eFileActionClose: {
+ const int error_code =
+ ::posix_spawn_file_actions_addclose(file_actions, action.GetFD());
+ if (error_code != 0) {
+ error.SetError(error_code, eErrorTypePOSIX);
+ return error;
}
-
- int error_code;
- if ((error_code = ::posix_spawnattr_init(&attr)) != 0)
- {
- if (log)
- log->Printf("::posix_spawnattr_init(&attr) failed");
- error.SetError(error_code, eErrorTypePOSIX);
- return error;
+ break;
+ }
+
+ case FileAction::eFileActionDuplicate: {
+ const int error_code = ::posix_spawn_file_actions_adddup2(
+ file_actions, action.GetFD(), action.GetActionArgument());
+ if (error_code != 0) {
+ error.SetError(error_code, eErrorTypePOSIX);
+ return error;
}
+ break;
+ }
- // Ensure we clean up the spawnattr structure however we exit this
- // function.
- std::unique_ptr<posix_spawnattr_t, int(*)(posix_spawnattr_t*)>
- spawnattr_up(&attr, ::posix_spawnattr_destroy);
-
-
- flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETSIGDEF |
- POSIX_SPAWN_SETSIGMASK;
- if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR))
- 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);
-
- if ((error_code = ::posix_spawnattr_setflags(&attr, flags)) != 0)
- {
- if (log)
- log->Printf("::posix_spawnattr_setflags(&attr, "
- "POSIX_SPAWN_START_SUSPENDED%s) failed: %s",
- flags & _POSIX_SPAWN_DISABLE_ASLR ?
- " | _POSIX_SPAWN_DISABLE_ASLR" : "",
- strerror(error_code));
- error.SetError(error_code, eErrorTypePOSIX);
- return error;
- }
+ case FileAction::eFileActionNone:
+ default:
+ if (log)
+ log->Printf("%s(): unsupported file action %u", __FUNCTION__,
+ action.GetAction());
+ break;
+ }
-#if !defined(__arm__)
+ return error;
+}
- // 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...
- cpu_type_t desired_cpu_type =
- launch_info.GetArchitecture().GetMachOCPUType();
- if (desired_cpu_type != LLDB_INVALID_CPUTYPE)
- {
- size_t ocount = 0;
- error_code = ::posix_spawnattr_setbinpref_np(&attr, 1,
- &desired_cpu_type,
- &ocount);
- if (error_code != 0)
- {
- if (log)
- log->Printf("::posix_spawnattr_setbinpref_np(&attr, 1, "
- "cpu_type = 0x%8.8x, count => %llu): %s",
- desired_cpu_type, (uint64_t)ocount,
- strerror(error_code));
- error.SetError(error_code, eErrorTypePOSIX);
- return error;
- }
- if (ocount != 1)
- {
- error.SetErrorStringWithFormat("posix_spawnattr_setbinpref_np "
- "did not set the expected number "
- "of cpu_type entries: expected 1 "
- "but was %zu", ocount);
- return error;
- }
- }
-#endif
+static Error PosixSpawnChildForPTraceDebugging(const char *path,
+ ProcessLaunchInfo &launch_info,
+ ::pid_t *pid,
+ cpu_type_t *actual_cpu_type) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- posix_spawn_file_actions_t file_actions;
- if ((error_code = ::posix_spawn_file_actions_init(&file_actions)) != 0)
- {
- if (log)
- log->Printf("::posix_spawn_file_actions_init(&file_actions) "
- "failed: %s",
- strerror(error_code));
- error.SetError(error_code, eErrorTypePOSIX);
- return error;
- }
+ if (!pid) {
+ error.SetErrorStringWithFormat("%s(): pid arg cannot be null",
+ __FUNCTION__);
+ return error;
+ }
+
+ posix_spawnattr_t attr;
+ short flags;
+ if (log) {
+ StreamString stream;
+ stream.Printf("%s(path='%s',...)\n", __FUNCTION__, path);
+ launch_info.Dump(stream, nullptr);
+ stream.Flush();
+ log->PutCString(stream.GetString().c_str());
+ }
+
+ int error_code;
+ if ((error_code = ::posix_spawnattr_init(&attr)) != 0) {
+ if (log)
+ log->Printf("::posix_spawnattr_init(&attr) failed");
+ error.SetError(error_code, eErrorTypePOSIX);
+ return error;
+ }
+
+ // Ensure we clean up the spawnattr structure however we exit this
+ // function.
+ std::unique_ptr<posix_spawnattr_t, int (*)(posix_spawnattr_t *)> spawnattr_up(
+ &attr, ::posix_spawnattr_destroy);
+
+ flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETSIGDEF |
+ POSIX_SPAWN_SETSIGMASK;
+ if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR))
+ 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);
+
+ if ((error_code = ::posix_spawnattr_setflags(&attr, flags)) != 0) {
+ if (log)
+ log->Printf("::posix_spawnattr_setflags(&attr, "
+ "POSIX_SPAWN_START_SUSPENDED%s) failed: %s",
+ flags & _POSIX_SPAWN_DISABLE_ASLR
+ ? " | _POSIX_SPAWN_DISABLE_ASLR"
+ : "",
+ strerror(error_code));
+ error.SetError(error_code, eErrorTypePOSIX);
+ return error;
+ }
- // Ensure we clean up file actions however we exit this. When the
- // file_actions_up below goes out of scope, we'll get our file action
- // cleanup.
- std::unique_ptr<posix_spawn_file_actions_t,
- int(*)(posix_spawn_file_actions_t*)>
- file_actions_up(&file_actions, ::posix_spawn_file_actions_destroy);
-
- // We assume the caller has setup the file actions appropriately. We
- // are not in the business of figuring out what we really need here.
- // lldb-server will have already called FinalizeFileActions() as well
- // to button these up properly.
- const size_t num_actions = launch_info.GetNumFileActions();
- for (size_t action_index = 0; action_index < num_actions; ++action_index)
- {
- const FileAction *const action =
- launch_info.GetFileActionAtIndex(action_index);
- if (!action)
- continue;
-
- error = CreatePosixSpawnFileAction(*action, &file_actions);
- if (!error.Success())
- {
- if (log)
- log->Printf("%s(): error converting FileAction to posix_spawn "
- "file action: %s", __FUNCTION__, error.AsCString());
- return error;
- }
- }
+#if !defined(__arm__)
- // TODO: Verify if we can set the working directory back immediately
- // after the posix_spawnp call without creating a race condition???
- const char *const working_directory =
- launch_info.GetWorkingDirectory().GetCString();
- if (working_directory && working_directory[0])
- ::chdir(working_directory);
-
- auto argv = launch_info.GetArguments().GetArgumentVector();
- auto envp = launch_info.GetEnvironmentEntries().GetArgumentVector();
- error_code = ::posix_spawnp(pid, path, &file_actions, &attr,
- (char * const*)argv, (char * const*)envp);
- if (error_code != 0)
- {
- if (log)
- log->Printf("::posix_spawnp(pid => %p, path = '%s', file_actions "
- "= %p, attr = %p, argv = %p, envp = %p) failed: %s",
- pid, path, &file_actions, &attr, argv, envp,
- strerror(error_code));
- error.SetError(error_code, eErrorTypePOSIX);
- return error;
+ // 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...
+ cpu_type_t desired_cpu_type = launch_info.GetArchitecture().GetMachOCPUType();
+ if (desired_cpu_type != LLDB_INVALID_CPUTYPE) {
+ size_t ocount = 0;
+ error_code =
+ ::posix_spawnattr_setbinpref_np(&attr, 1, &desired_cpu_type, &ocount);
+ if (error_code != 0) {
+ if (log)
+ log->Printf("::posix_spawnattr_setbinpref_np(&attr, 1, "
+ "cpu_type = 0x%8.8x, count => %llu): %s",
+ desired_cpu_type, (uint64_t)ocount, strerror(error_code));
+ error.SetError(error_code, eErrorTypePOSIX);
+ return error;
}
-
- // Validate we got a pid.
- if (pid == LLDB_INVALID_PROCESS_ID)
- {
- error.SetErrorString("posix_spawn() did not indicate a failure but it "
- "failed to return a pid, aborting.");
- return error;
+ if (ocount != 1) {
+ error.SetErrorStringWithFormat("posix_spawnattr_setbinpref_np "
+ "did not set the expected number "
+ "of cpu_type entries: expected 1 "
+ "but was %zu",
+ ocount);
+ return error;
}
+ }
+#endif
- if (actual_cpu_type)
- {
- *actual_cpu_type = GetCPUTypeForLocalProcess(*pid);
- if (log)
- log->Printf("%s(): cpu type for launched process pid=%i: "
- "cpu_type=0x%8.8x", __FUNCTION__, *pid,
- *actual_cpu_type);
+ posix_spawn_file_actions_t file_actions;
+ if ((error_code = ::posix_spawn_file_actions_init(&file_actions)) != 0) {
+ if (log)
+ log->Printf("::posix_spawn_file_actions_init(&file_actions) "
+ "failed: %s",
+ strerror(error_code));
+ error.SetError(error_code, eErrorTypePOSIX);
+ return error;
+ }
+
+ // Ensure we clean up file actions however we exit this. When the
+ // file_actions_up below goes out of scope, we'll get our file action
+ // cleanup.
+ std::unique_ptr<posix_spawn_file_actions_t,
+ int (*)(posix_spawn_file_actions_t *)>
+ file_actions_up(&file_actions, ::posix_spawn_file_actions_destroy);
+
+ // We assume the caller has setup the file actions appropriately. We
+ // are not in the business of figuring out what we really need here.
+ // lldb-server will have already called FinalizeFileActions() as well
+ // to button these up properly.
+ const size_t num_actions = launch_info.GetNumFileActions();
+ for (size_t action_index = 0; action_index < num_actions; ++action_index) {
+ const FileAction *const action =
+ launch_info.GetFileActionAtIndex(action_index);
+ if (!action)
+ continue;
+
+ error = CreatePosixSpawnFileAction(*action, &file_actions);
+ if (!error.Success()) {
+ if (log)
+ log->Printf("%s(): error converting FileAction to posix_spawn "
+ "file action: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
}
-
+ }
+
+ // TODO: Verify if we can set the working directory back immediately
+ // after the posix_spawnp call without creating a race condition???
+ const char *const working_directory =
+ launch_info.GetWorkingDirectory().GetCString();
+ if (working_directory && working_directory[0])
+ ::chdir(working_directory);
+
+ auto argv = launch_info.GetArguments().GetArgumentVector();
+ auto envp = launch_info.GetEnvironmentEntries().GetArgumentVector();
+ error_code = ::posix_spawnp(pid, path, &file_actions, &attr,
+ (char *const *)argv, (char *const *)envp);
+ if (error_code != 0) {
+ if (log)
+ log->Printf("::posix_spawnp(pid => %p, path = '%s', file_actions "
+ "= %p, attr = %p, argv = %p, envp = %p) failed: %s",
+ pid, path, &file_actions, &attr, argv, envp,
+ strerror(error_code));
+ error.SetError(error_code, eErrorTypePOSIX);
return error;
-}
+ }
-Error
-LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
- LaunchFlavor *launch_flavor)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- if (!launch_flavor)
- {
- error.SetErrorString("mandatory launch_flavor field was null");
- return error;
- }
+ // Validate we got a pid.
+ if (pid == LLDB_INVALID_PROCESS_ID) {
+ error.SetErrorString("posix_spawn() did not indicate a failure but it "
+ "failed to return a pid, aborting.");
+ return error;
+ }
+ if (actual_cpu_type) {
+ *actual_cpu_type = GetCPUTypeForLocalProcess(*pid);
if (log)
- {
- StreamString stream;
- stream.Printf("NativeProcessDarwin::%s(): launching with the "
- "following launch info:", __FUNCTION__);
- launch_info.Dump(stream, nullptr);
- stream.Flush();
- log->PutCString(stream.GetString().c_str());
- }
+ log->Printf("%s(): cpu type for launched process pid=%i: "
+ "cpu_type=0x%8.8x",
+ __FUNCTION__, *pid, *actual_cpu_type);
+ }
+
+ return error;
+}
- // Retrieve the binary name given to us.
- char given_path[PATH_MAX];
- given_path[0] = '\0';
- launch_info.GetExecutableFile().GetPath(given_path, sizeof(given_path));
-
- // Determine the manner in which we'll launch.
- *launch_flavor = g_launch_flavor;
- if (*launch_flavor == LaunchFlavor::Default)
- {
- // Our default launch method is posix spawn
- *launch_flavor = LaunchFlavor::PosixSpawn;
+Error LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
+ LaunchFlavor *launch_flavor) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ if (!launch_flavor) {
+ error.SetErrorString("mandatory launch_flavor field was null");
+ return error;
+ }
+
+ if (log) {
+ StreamString stream;
+ stream.Printf("NativeProcessDarwin::%s(): launching with the "
+ "following launch info:",
+ __FUNCTION__);
+ launch_info.Dump(stream, nullptr);
+ stream.Flush();
+ log->PutCString(stream.GetString().c_str());
+ }
+
+ // Retrieve the binary name given to us.
+ char given_path[PATH_MAX];
+ given_path[0] = '\0';
+ launch_info.GetExecutableFile().GetPath(given_path, sizeof(given_path));
+
+ // Determine the manner in which we'll launch.
+ *launch_flavor = g_launch_flavor;
+ if (*launch_flavor == LaunchFlavor::Default) {
+ // Our default launch method is posix spawn
+ *launch_flavor = LaunchFlavor::PosixSpawn;
#if defined WITH_FBS
- // Check if we have an app bundle, if so launch using BackBoard Services.
- if (strstr(given_path, ".app"))
- {
- *launch_flavor = eLaunchFlavorFBS;
- }
+ // Check if we have an app bundle, if so launch using BackBoard Services.
+ if (strstr(given_path, ".app")) {
+ *launch_flavor = eLaunchFlavorFBS;
+ }
#elif defined WITH_BKS
- // Check if we have an app bundle, if so launch using BackBoard Services.
- if (strstr(given_path, ".app"))
- {
- *launch_flavor = eLaunchFlavorBKS;
- }
+ // Check if we have an app bundle, if so launch using BackBoard Services.
+ if (strstr(given_path, ".app")) {
+ *launch_flavor = eLaunchFlavorBKS;
+ }
#elif defined WITH_SPRINGBOARD
- // Check if we have an app bundle, if so launch using SpringBoard.
- if (strstr(given_path, ".app"))
- {
- *launch_flavor = eLaunchFlavorSpringBoard;
- }
-#endif
+ // Check if we have an app bundle, if so launch using SpringBoard.
+ if (strstr(given_path, ".app")) {
+ *launch_flavor = eLaunchFlavorSpringBoard;
}
+#endif
+ }
+
+ // Attempt to resolve the binary name to an absolute path.
+ char resolved_path[PATH_MAX];
+ resolved_path[0] = '\0';
- // Attempt to resolve the binary name to an absolute path.
- char resolved_path[PATH_MAX];
- resolved_path[0] = '\0';
+ if (log)
+ log->Printf("%s(): attempting to resolve given binary path: \"%s\"",
+ __FUNCTION__, given_path);
+ // If we fail to resolve the path to our executable, then just use what we
+ // were given and hope for the best
+ if (!ResolveExecutablePath(given_path, resolved_path,
+ sizeof(resolved_path))) {
if (log)
- log->Printf("%s(): attempting to resolve given binary path: \"%s\"",
- __FUNCTION__, given_path);
-
- // If we fail to resolve the path to our executable, then just use what we
- // were given and hope for the best
- if (!ResolveExecutablePath(given_path, resolved_path,
- sizeof(resolved_path)) )
- {
- if (log)
- log->Printf("%s(): failed to resolve binary path, using "
- "what was given verbatim and hoping for the best",
- __FUNCTION__);
- ::strncpy(resolved_path, given_path,
- sizeof(resolved_path));
- }
- else
- {
- if (log)
- log->Printf("%s(): resolved given binary path to: \"%s\"",
- __FUNCTION__, resolved_path);
- }
+ log->Printf("%s(): failed to resolve binary path, using "
+ "what was given verbatim and hoping for the best",
+ __FUNCTION__);
+ ::strncpy(resolved_path, given_path, sizeof(resolved_path));
+ } else {
+ if (log)
+ log->Printf("%s(): resolved given binary path to: \"%s\"", __FUNCTION__,
+ resolved_path);
+ }
+
+ char launch_err_str[PATH_MAX];
+ launch_err_str[0] = '\0';
- char launch_err_str[PATH_MAX];
- launch_err_str[0] = '\0';
-
- // TODO figure out how to handle QSetProcessEvent
- // const char *process_event = ctx.GetProcessEvent();
-
- // Ensure the binary is there.
- struct stat path_stat;
- if (::stat(resolved_path, &path_stat) == -1)
- {
- error.SetErrorToErrno();
- return error;
+ // TODO figure out how to handle QSetProcessEvent
+ // const char *process_event = ctx.GetProcessEvent();
+
+ // Ensure the binary is there.
+ struct stat path_stat;
+ if (::stat(resolved_path, &path_stat) == -1) {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ // Fork a child process for debugging
+ // state_callback(eStateLaunching);
+
+ const auto argv = launch_info.GetArguments().GetConstArgumentVector();
+ const auto envp =
+ launch_info.GetEnvironmentEntries().GetConstArgumentVector();
+
+ switch (*launch_flavor) {
+ case LaunchFlavor::ForkExec: {
+ ::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ error = ForkChildForPTraceDebugging(resolved_path, argv, envp, &pid,
+ pty_master_fd);
+ if (error.Success()) {
+ launch_info.SetProcessID(static_cast<lldb::pid_t>(pid));
+ } else {
+ // Reset any variables that might have been set during a failed
+ // launch attempt.
+ if (pty_master_fd)
+ *pty_master_fd = -1;
+
+ // We're done.
+ return error;
}
-
- // Fork a child process for debugging
- // state_callback(eStateLaunching);
-
- const auto argv = launch_info.GetArguments().GetConstArgumentVector();
- const auto envp =
- launch_info.GetEnvironmentEntries().GetConstArgumentVector();
-
- switch (*launch_flavor)
- {
- case LaunchFlavor::ForkExec:
- {
- ::pid_t pid = LLDB_INVALID_PROCESS_ID;
- error = ForkChildForPTraceDebugging(resolved_path, argv, envp,
- &pid, pty_master_fd);
- if (error.Success())
- {
- launch_info.SetProcessID(static_cast<lldb::pid_t>(pid));
- }
- else
- {
- // Reset any variables that might have been set during a failed
- // launch attempt.
- if (pty_master_fd)
- *pty_master_fd = -1;
-
- // We're done.
- return error;
- }
- }
- break;
+ } break;
#ifdef WITH_FBS
- case LaunchFlavor::FBS:
- {
- 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 LaunchFlavor::FBS: {
+ 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 LaunchFlavor::BKS:
- {
- 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 LaunchFlavor::BKS: {
+ 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 LaunchFlavor::SpringBoard:
- {
- // .../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 LaunchFlavor::PosixSpawn:
- {
- ::pid_t pid = LLDB_INVALID_PROCESS_ID;
-
- // Retrieve paths for stdin/stdout/stderr.
- cpu_type_t actual_cpu_type = 0;
- error = PosixSpawnChildForPTraceDebugging(resolved_path,
- launch_info,
- &pid,
- &actual_cpu_type);
- if (error.Success())
- {
- launch_info.SetProcessID(static_cast<lldb::pid_t>(pid));
- if (pty_master_fd)
- *pty_master_fd = launch_info.GetPTY().
- ReleaseMasterFileDescriptor();
- }
- else
- {
- // Reset any variables that might have been set during a failed
- // launch attempt.
- if (pty_master_fd)
- *pty_master_fd = -1;
-
- // We're done.
- return error;
- }
- break;
+ case LaunchFlavor::SpringBoard: {
+ // .../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;
}
-
- default:
- // Invalid launch flavor.
- error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): unknown "
- "launch flavor %d", __FUNCTION__,
- (int)*launch_flavor);
- return error;
+ }
}
-
- if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID)
- {
- // If we don't have a valid process ID and no one has set the error,
- // then return a generic error.
- if (error.Success())
- error.SetErrorStringWithFormat("%s(): failed to launch, no reason "
- "specified", __FUNCTION__);
+ 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
- // We're done with the launch side of the operation.
+ case LaunchFlavor::PosixSpawn: {
+ ::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+ // Retrieve paths for stdin/stdout/stderr.
+ cpu_type_t actual_cpu_type = 0;
+ error = PosixSpawnChildForPTraceDebugging(resolved_path, launch_info, &pid,
+ &actual_cpu_type);
+ if (error.Success()) {
+ launch_info.SetProcessID(static_cast<lldb::pid_t>(pid));
+ if (pty_master_fd)
+ *pty_master_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
+ } else {
+ // Reset any variables that might have been set during a failed
+ // launch attempt.
+ if (pty_master_fd)
+ *pty_master_fd = -1;
+
+ // We're done.
+ return error;
+ }
+ break;
+ }
+
+ default:
+ // Invalid launch flavor.
+ error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): unknown "
+ "launch flavor %d",
+ __FUNCTION__, (int)*launch_flavor);
return error;
+ }
+
+ if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) {
+ // If we don't have a valid process ID and no one has set the error,
+ // then return a generic error.
+ if (error.Success())
+ error.SetErrorStringWithFormat("%s(): failed to launch, no reason "
+ "specified",
+ __FUNCTION__);
+ }
+
+ // We're done with the launch side of the operation.
+ return error;
}
-
-}} // namespaces
-
+}
+} // namespaces
diff --git a/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.h b/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.h
index d06056afbb6..d1af4d09f8b 100644
--- a/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.h
+++ b/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.h
@@ -23,10 +23,8 @@
#include "LaunchFlavor.h"
-namespace lldb_private
-{
-namespace darwin_process_launcher
-{
+namespace lldb_private {
+namespace darwin_process_launcher {
// =============================================================================
/// Launches a process for debugging.
///
@@ -41,9 +39,8 @@ namespace darwin_process_launcher
/// @param[out] launch_flavor
/// Contains the launch flavor used when launching the process.
// =============================================================================
-Error
-LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
- lldb_private::process_darwin::LaunchFlavor *launch_flavor);
+Error LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
+ lldb_private::process_darwin::LaunchFlavor *launch_flavor);
} // darwin_process_launcher
} // lldb_private
diff --git a/lldb/source/Plugins/Process/Darwin/LaunchFlavor.h b/lldb/source/Plugins/Process/Darwin/LaunchFlavor.h
index 02182f7528a..7b161712cff 100644
--- a/lldb/source/Plugins/Process/Darwin/LaunchFlavor.h
+++ b/lldb/source/Plugins/Process/Darwin/LaunchFlavor.h
@@ -13,22 +13,21 @@
namespace lldb_private {
namespace process_darwin {
-enum class LaunchFlavor
-{
- Default = 0,
- PosixSpawn = 1,
- ForkExec = 2,
+enum class LaunchFlavor {
+ Default = 0,
+ PosixSpawn = 1,
+ ForkExec = 2,
#ifdef WITH_SPRINGBOARD
- SpringBoard = 3,
+ SpringBoard = 3,
#endif
#ifdef WITH_BKS
- BKS = 4,
+ BKS = 4,
#endif
#ifdef WITH_FBS
- FBS = 5
+ FBS = 5
#endif
};
-
-}} // namespaces
+}
+} // namespaces
#endif /* LaunchFlavor_h */
diff --git a/lldb/source/Plugins/Process/Darwin/MachException.cpp b/lldb/source/Plugins/Process/Darwin/MachException.cpp
index d9693195e38..81706441494 100644
--- a/lldb/source/Plugins/Process/Darwin/MachException.cpp
+++ b/lldb/source/Plugins/Process/Darwin/MachException.cpp
@@ -15,8 +15,8 @@
// C includes
#include <errno.h>
-#include <sys/types.h>
#include <sys/ptrace.h>
+#include <sys/types.h>
// C++ includes
#include <mutex>
@@ -33,51 +33,29 @@ using namespace lldb_private;
using namespace lldb_private::process_darwin;
// 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
@@ -86,107 +64,71 @@ extern "C" boolean_t mach_exc_server(
static MachException::Data *g_message = NULL;
-
-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
-)
-{
- // TODO change to LIBLLDB_LOG_EXCEPTION
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
- if (log)
- {
- log->Printf("::%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(
+ 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) {
+ // TODO change to LIBLLDB_LOG_EXCEPTION
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+ if (log) {
+ log->Printf("::%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
-)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
- if (log)
- {
- log->Printf("::%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_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) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+ if (log) {
+ log->Printf("::%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)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
- if (log)
- {
- log->Printf("::%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;
+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) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+ if (log) {
+ log->Printf("::%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;
}
#if 0
@@ -216,316 +158,249 @@ MachException::Message::Dump(Stream &stream) const
}
#endif
-bool
-MachException::Data::GetStopInfo(struct ThreadStopInfo *stop_info,
- const UnixSignals &signals,
- Stream &stream) const
-{
- if (!stop_info)
- return false;
+bool MachException::Data::GetStopInfo(struct ThreadStopInfo *stop_info,
+ const UnixSignals &signals,
+ Stream &stream) const {
+ if (!stop_info)
+ return false;
- // Zero out the structure.
- memset(stop_info, 0, sizeof(struct ThreadStopInfo));
+ // Zero out the structure.
+ memset(stop_info, 0, sizeof(struct ThreadStopInfo));
- if (exc_type == 0)
- {
- stop_info->reason = eStopReasonInvalid;
- return true;
- }
-
- // We always stop with a mach exception.
- stop_info->reason = eStopReasonException;
- // 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);
- if (exc_name)
- stream.Printf("%s", exc_name);
- else
- stream.Printf("%i", exc_type);
-
- stop_info->details.exception.data_count = exc_data.size();
-
- int soft_signal = SoftSignal();
- if (soft_signal)
- {
- const char *sig_str = signals.GetSignalAsCString(soft_signal);
- stream.Printf(" EXC_SOFT_SIGNAL( %i ( %s ))", soft_signal,
- sig_str ? sig_str : "unknown signal");
- }
- else
- {
- // No special disassembly for exception data, just print it.
- size_t idx;
- stream.Printf(" data[%llu] = {",
- (uint64_t)stop_info->details.exception.data_count);
-
- for (idx = 0; idx < stop_info->details.exception.data_count; ++idx)
- {
- stream.Printf("0x%llx%c", (uint64_t)exc_data[idx],
- ((idx + 1 == stop_info->details.exception.data_count)
- ? '}' : ','));
- }
+ if (exc_type == 0) {
+ stop_info->reason = eStopReasonInvalid;
+ return true;
+ }
+
+ // We always stop with a mach exception.
+ stop_info->reason = eStopReasonException;
+ // 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);
+ if (exc_name)
+ stream.Printf("%s", exc_name);
+ else
+ stream.Printf("%i", exc_type);
+
+ stop_info->details.exception.data_count = exc_data.size();
+
+ int soft_signal = SoftSignal();
+ if (soft_signal) {
+ const char *sig_str = signals.GetSignalAsCString(soft_signal);
+ stream.Printf(" EXC_SOFT_SIGNAL( %i ( %s ))", soft_signal,
+ sig_str ? sig_str : "unknown signal");
+ } else {
+ // No special disassembly for exception data, just print it.
+ size_t idx;
+ stream.Printf(" data[%llu] = {",
+ (uint64_t)stop_info->details.exception.data_count);
+
+ for (idx = 0; idx < stop_info->details.exception.data_count; ++idx) {
+ stream.Printf(
+ "0x%llx%c", (uint64_t)exc_data[idx],
+ ((idx + 1 == stop_info->details.exception.data_count) ? '}' : ','));
}
+ }
- // Copy the exception data
- for (size_t i = 0; i < stop_info->details.exception.data_count; i++)
- stop_info->details.exception.data[i] = exc_data[i];
+ // Copy the exception data
+ for (size_t i = 0; i < stop_info->details.exception.data_count; i++)
+ stop_info->details.exception.data[i] = exc_data[i];
- return true;
+ return true;
}
-Error
-MachException::Message::Receive(mach_port_t port, mach_msg_option_t options,
- mach_msg_timeout_t timeout,
- mach_port_t notify_port)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
-
- mach_msg_timeout_t mach_msg_timeout =
- options & MACH_RCV_TIMEOUT ? timeout : 0;
- if (log && ((options & MACH_RCV_TIMEOUT) == 0))
- {
- // Dump this log message if we have no timeout in case it never returns
- log->Printf("::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);
- }
-
- mach_msg_return_t mach_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);
- error.SetError(mach_err, eErrorTypeMachKernel);
+Error MachException::Message::Receive(mach_port_t port,
+ mach_msg_option_t options,
+ mach_msg_timeout_t timeout,
+ mach_port_t notify_port) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+
+ mach_msg_timeout_t mach_msg_timeout =
+ options & MACH_RCV_TIMEOUT ? timeout : 0;
+ if (log && ((options & MACH_RCV_TIMEOUT) == 0)) {
+ // Dump this log message if we have no timeout in case it never returns
+ log->Printf("::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);
+ }
+
+ mach_msg_return_t mach_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);
+ error.SetError(mach_err, eErrorTypeMachKernel);
+
+ // Dump any errors we get
+ if (error.Fail() && log) {
+ log->Printf("::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 = %lu, rcv_name "
+ "= %#x, timeout = %u, notify = %#x) failed: %s",
+ 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,
+ error.AsCString());
+ }
+ return error;
+}
- // Dump any errors we get
- if (error.Fail() && log)
- {
- log->Printf("::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 = %lu, rcv_name "
- "= %#x, timeout = %u, notify = %#x) failed: %s",
- 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,
- error.AsCString());
- }
- return error;
+void MachException::Message::Dump(Stream &stream) const {
+ stream.Printf(" 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 }\n",
+ 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);
+
+ stream.Printf(" 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);
}
-void
-MachException::Message::Dump(Stream &stream) const
-{
- stream.Printf(" 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 }\n",
- 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);
-
- stream.Printf(" 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);
+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 {
+ Log *log(
+ GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+ if (log)
+ log->Printf("MachException::Message::%s(): mach_exc_server "
+ "returned zero...",
+ __FUNCTION__);
+ }
+ g_message = NULL;
+ return success;
}
-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
- {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
+Error MachException::Message::Reply(::pid_t inferior_pid, task_t inferior_task,
+ int signal) {
+ // Reply to the exception...
+ Error error;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+
+ // 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 (inferior_task == state.task_port) {
+ // This is our task, so we can update the signal to send to it
+ state_pid = inferior_pid;
+ soft_signal = signal;
+ } else {
+ auto mach_err = ::pid_for_task(state.task_port, &state_pid);
+ if (mach_err) {
+ error.SetError(mach_err, eErrorTypeMachKernel);
if (log)
- log->Printf("MachException::Message::%s(): mach_exc_server "
- "returned zero...", __FUNCTION__);
+ log->Printf("MachException::Message::%s(): pid_for_task() "
+ "failed: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ }
}
- g_message = NULL;
- return success;
-}
-Error
-MachException::Message::Reply(::pid_t inferior_pid, task_t inferior_task,
- int signal)
-{
- // Reply to the exception...
- Error error;
-
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
-
- // 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 (inferior_task == state.task_port)
- {
- // This is our task, so we can update the signal to send to it
- state_pid = inferior_pid;
- soft_signal = signal;
- }
- else
- {
- auto mach_err = ::pid_for_task(state.task_port, &state_pid);
- if (mach_err)
- {
- error.SetError(mach_err, eErrorTypeMachKernel);
- if (log)
- log->Printf("MachException::Message::%s(): pid_for_task() "
- "failed: %s", __FUNCTION__, error.AsCString());
- return error;
- }
- }
+ lldbassert(state_pid != -1);
+ if (state_pid != -1) {
+ errno = 0;
+ caddr_t thread_port_caddr = (caddr_t)(uintptr_t)state.thread_port;
+ if (::ptrace(PT_THUPDATE, state_pid, thread_port_caddr, soft_signal) != 0)
+ error.SetError(errno, eErrorTypePOSIX);
- lldbassert(state_pid != -1);
- if (state_pid != -1)
- {
- errno = 0;
- caddr_t thread_port_caddr = (caddr_t)(uintptr_t)state.thread_port;
- if (::ptrace(PT_THUPDATE, state_pid, thread_port_caddr, soft_signal)
- != 0)
- error.SetError(errno, eErrorTypePOSIX);
-
- if (!error.Success())
- {
- if (log)
- log->Printf("::ptrace(request = PT_THUPDATE, pid = "
- "0x%4.4x, tid = 0x%4.4x, signal = %i)",
- state_pid, state.thread_port, soft_signal);
- return error;
- }
- }
+ if (!error.Success()) {
+ if (log)
+ log->Printf("::ptrace(request = PT_THUPDATE, pid = "
+ "0x%4.4x, tid = 0x%4.4x, signal = %i)",
+ state_pid, state.thread_port, soft_signal);
+ return error;
+ }
}
+ }
+
+ if (log)
+ log->Printf("::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);
+
+ auto mach_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 (mach_err)
+ error.SetError(mach_err, eErrorTypeMachKernel);
- if (log)
- log->Printf("::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);
-
- auto mach_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 (mach_err)
- error.SetError(mach_err, eErrorTypeMachKernel);
-
- // Log our error if we have one.
- if (error.Fail() && log)
- {
- if (error.GetError() == MACH_SEND_INTERRUPTED)
- {
- log->PutCString("::mach_msg() - send interrupted");
- // TODO: keep retrying to reply???
- }
- else if (state.task_port == inferior_task)
- {
- log->Printf("mach_msg(): returned an error when replying "
- "to a mach exception: error = %u (%s)",
- error.GetError(), error.AsCString());
- }
- else
- {
- log->Printf("::mach_msg() - failed (child of task): %u (%s)",
- error.GetError(), error.AsCString());
- }
+ // Log our error if we have one.
+ if (error.Fail() && log) {
+ if (error.GetError() == MACH_SEND_INTERRUPTED) {
+ log->PutCString("::mach_msg() - send interrupted");
+ // TODO: keep retrying to reply???
+ } else if (state.task_port == inferior_task) {
+ log->Printf("mach_msg(): returned an error when replying "
+ "to a mach exception: error = %u (%s)",
+ error.GetError(), error.AsCString());
+ } else {
+ log->Printf("::mach_msg() - failed (child of task): %u (%s)",
+ error.GetError(), error.AsCString());
}
+ }
- return error;
+ return error;
}
-#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)
+#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
@@ -537,148 +412,132 @@ MachException::Message::Reply(::pid_t inferior_pid, task_t inferior_task,
#define LLDB_EXC_MASK (EXC_MASK_ALL & ~EXC_MASK_RESOURCE)
-Error
-MachException::PortInfo::Save(task_t task)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
+Error MachException::PortInfo::Save(task_t task) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
- if (log)
- log->Printf("MachException::PortInfo::%s(task = 0x%4.4x)",
- __FUNCTION__, task);
+ if (log)
+ log->Printf("MachException::PortInfo::%s(task = 0x%4.4x)", __FUNCTION__,
+ 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
- mask = LLDB_EXC_MASK;
+ // 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
+ mask = LLDB_EXC_MASK;
- count = (sizeof(ports) / sizeof(ports[0]));
- auto mach_err = ::task_get_exception_ports(task, mask, masks, &count, ports,
- behaviors, flavors);
- if (mach_err)
- error.SetError(mach_err, eErrorTypeMachKernel);
+ count = (sizeof(ports) / sizeof(ports[0]));
+ auto mach_err = ::task_get_exception_ports(task, mask, masks, &count, ports,
+ behaviors, flavors);
+ if (mach_err)
+ error.SetError(mach_err, eErrorTypeMachKernel);
- if (log)
- {
- if (error.Success())
- {
- log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = "
- "0x%x, maskCnt => %u, ports, behaviors, flavors)",
- task, mask, count);
- }
- else
- {
- log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = 0x%x, "
- "maskCnt => %u, ports, behaviors, flavors) error: %u (%s)",
- task, mask, count, error.GetError(), error.AsCString());
- }
+ if (log) {
+ if (error.Success()) {
+ log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = "
+ "0x%x, maskCnt => %u, ports, behaviors, flavors)",
+ task, mask, count);
+ } else {
+ log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = 0x%x, "
+ "maskCnt => %u, ports, behaviors, flavors) error: %u (%s)",
+ task, mask, count, error.GetError(), error.AsCString());
}
+ }
- if ((error.GetError() == KERN_INVALID_ARGUMENT) &&
- (mask != PREV_EXC_MASK_ALL))
- {
- mask = PREV_EXC_MASK_ALL;
- count = (sizeof(ports) / sizeof(ports[0]));
- mach_err = ::task_get_exception_ports(task, mask, masks, &count, ports,
- behaviors, flavors);
- error.SetError(mach_err, eErrorTypeMachKernel);
- if (log)
- {
- if (error.Success())
- {
- log->Printf("::task_get_exception_ports(task = 0x%4.4x, "
- "mask = 0x%x, maskCnt => %u, ports, behaviors, "
- "flavors)", task, mask, count);
- }
- else
- {
- log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = "
- "0x%x, maskCnt => %u, ports, behaviors, flavors) "
- "error: %u (%s)", task, mask, count,
- error.GetError(), error.AsCString());
- }
- }
- }
- if (error.Fail())
- {
- mask = 0;
- count = 0;
+ if ((error.GetError() == KERN_INVALID_ARGUMENT) &&
+ (mask != PREV_EXC_MASK_ALL)) {
+ mask = PREV_EXC_MASK_ALL;
+ count = (sizeof(ports) / sizeof(ports[0]));
+ mach_err = ::task_get_exception_ports(task, mask, masks, &count, ports,
+ behaviors, flavors);
+ error.SetError(mach_err, eErrorTypeMachKernel);
+ if (log) {
+ if (error.Success()) {
+ log->Printf("::task_get_exception_ports(task = 0x%4.4x, "
+ "mask = 0x%x, maskCnt => %u, ports, behaviors, "
+ "flavors)",
+ task, mask, count);
+ } else {
+ log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = "
+ "0x%x, maskCnt => %u, ports, behaviors, flavors) "
+ "error: %u (%s)",
+ task, mask, count, error.GetError(), error.AsCString());
+ }
}
- return error;
+ }
+ if (error.Fail()) {
+ mask = 0;
+ count = 0;
+ }
+ return error;
}
-Error
-MachException::PortInfo::Restore(task_t task)
-{
- Error error;
+Error MachException::PortInfo::Restore(task_t task) {
+ Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
- if (log)
- log->Printf("MachException::PortInfo::Restore(task = 0x%4.4x)", task);
-
- uint32_t i = 0;
- if (count > 0)
- {
- for (i = 0; i < count; i++)
- {
- auto mach_err = ::task_set_exception_ports(task, masks[i], ports[i],
- behaviors[i],
- flavors[i]);
- if (mach_err)
- error.SetError(mach_err, eErrorTypeMachKernel);
- if (log)
- {
- if (error.Success())
- {
- log->Printf("::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]);
- }
- else
- {
- log->Printf("::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): "
- "error %u (%s)", task, masks[i], ports[i],
- behaviors[i], flavors[i], error.GetError(),
- error.AsCString());
- }
- }
-
- // Bail if we encounter any errors
- if (error.Fail())
- break;
+ if (log)
+ log->Printf("MachException::PortInfo::Restore(task = 0x%4.4x)", task);
+
+ uint32_t i = 0;
+ if (count > 0) {
+ for (i = 0; i < count; i++) {
+ auto mach_err = ::task_set_exception_ports(task, masks[i], ports[i],
+ behaviors[i], flavors[i]);
+ if (mach_err)
+ error.SetError(mach_err, eErrorTypeMachKernel);
+ if (log) {
+ if (error.Success()) {
+ log->Printf("::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]);
+ } else {
+ log->Printf("::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): "
+ "error %u (%s)",
+ task, masks[i], ports[i], behaviors[i], flavors[i],
+ error.GetError(), error.AsCString());
}
+ }
+
+ // Bail if we encounter any errors
+ if (error.Fail())
+ break;
}
+ }
- count = 0;
- return error;
+ count = 0;
+ return 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";
+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";
+ case EXC_CRASH:
+ return "EXC_CRASH";
#endif
- default:
- break;
- }
- return NULL;
+ default:
+ break;
+ }
+ return NULL;
}
diff --git a/lldb/source/Plugins/Process/Darwin/MachException.h b/lldb/source/Plugins/Process/Darwin/MachException.h
index a96090b3bd8..ac8cd7030c5 100644
--- a/lldb/source/Plugins/Process/Darwin/MachException.h
+++ b/lldb/source/Plugins/Process/Darwin/MachException.h
@@ -11,150 +11,127 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef __MachException_h__
#define __MachException_h__
#include <mach/mach.h>
#include <vector>
+#include "lldb/Host/Debug.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/lldb-types.h"
-#include "lldb/Host/Debug.h"
-namespace lldb_private
-{
-namespace process_darwin
-{
+namespace lldb_private {
+namespace process_darwin {
-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;
-
- Error
- Save(task_t task);
-
- Error
- 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));
- }
-
- bool
- GetStopInfo(ThreadStopInfo *stop_info, const UnixSignals &signals,
- Stream &stream) 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);
-
- Error
- Reply(::pid_t inferior_pid, task_t inferior_task, int signal);
-
- Error
- Receive(mach_port_t receive_port,
- mach_msg_option_t options,
- mach_msg_timeout_t timeout,
- mach_port_t notify_port = MACH_PORT_NULL);
-
- void
- Dump(Stream &stream) const;
-
- 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;
+
+ Error Save(task_t task);
+
+ Error 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));
+ }
+
+ bool GetStopInfo(ThreadStopInfo *stop_info, const UnixSignals &signals,
+ Stream &stream) 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);
+
+ Error Reply(::pid_t inferior_pid, task_t inferior_task, int signal);
+
+ Error Receive(mach_port_t receive_port, mach_msg_option_t options,
+ mach_msg_timeout_t timeout,
+ mach_port_t notify_port = MACH_PORT_NULL);
+
+ void Dump(Stream &stream) const;
+
+ 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);
};
} // namespace process_darwin
diff --git a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
index d0eaac3c793..e56375ebaa4 100644
--- a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
+++ b/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
@@ -40,170 +40,142 @@ using namespace lldb_private::darwin_process_launcher;
// Hidden Impl
// -----------------------------------------------------------------------------
-namespace
-{
- struct hack_task_dyld_info {
- mach_vm_address_t all_image_info_addr;
- mach_vm_size_t all_image_info_size;
- };
+namespace {
+struct hack_task_dyld_info {
+ mach_vm_address_t all_image_info_addr;
+ mach_vm_size_t all_image_info_size;
+};
}
// -----------------------------------------------------------------------------
// Public Static Methods
// -----------------------------------------------------------------------------
-Error
-NativeProcessProtocol::Launch(ProcessLaunchInfo &launch_info,
- NativeProcessProtocol::NativeDelegate
- &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &native_process_sp)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- Error error;
-
- // Verify the working directory is valid if one was specified.
- FileSpec working_dir(launch_info.GetWorkingDirectory());
- if (working_dir &&
- (!working_dir.ResolvePath() ||
- working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
- {
- error.SetErrorStringWithFormat("No such file or directory: %s",
- working_dir.GetCString());
- return error;
- }
+Error NativeProcessProtocol::Launch(
+ ProcessLaunchInfo &launch_info,
+ NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop,
+ NativeProcessProtocolSP &native_process_sp) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ Error error;
+
+ // Verify the working directory is valid if one was specified.
+ FileSpec working_dir(launch_info.GetWorkingDirectory());
+ if (working_dir &&
+ (!working_dir.ResolvePath() ||
+ working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) {
+ error.SetErrorStringWithFormat("No such file or directory: %s",
+ working_dir.GetCString());
+ return error;
+ }
- // Launch the inferior.
- int pty_master_fd = -1;
- LaunchFlavor launch_flavor = LaunchFlavor::Default;
+ // Launch the inferior.
+ int pty_master_fd = -1;
+ LaunchFlavor launch_flavor = LaunchFlavor::Default;
- error = LaunchInferior(launch_info, &pty_master_fd, &launch_flavor);
+ error = LaunchInferior(launch_info, &pty_master_fd, &launch_flavor);
- // Handle launch failure.
- if (!error.Success())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s() failed to launch process: "
- "%s",
- __FUNCTION__, error.AsCString());
- return error;
- }
-
- // Handle failure to return a pid.
- if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s() launch succeeded but no "
- "pid was returned! Aborting.", __FUNCTION__);
- return error;
- }
-
- // Create the Darwin native process impl.
- std::shared_ptr<NativeProcessDarwin>
- np_darwin_sp(new NativeProcessDarwin(launch_info.GetProcessID(),
- pty_master_fd));
- if (!np_darwin_sp->RegisterNativeDelegate(native_delegate))
- {
- native_process_sp.reset ();
- error.SetErrorStringWithFormat ("failed to register the native delegate");
- return error;
- }
-
- // Finalize the processing needed to debug the launched process with
- // a NativeProcessDarwin instance.
- error = np_darwin_sp->FinalizeLaunch(launch_flavor, mainloop);
- if (!error.Success())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s() aborting, failed to finalize"
- " the launching of the process: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
+ // Handle launch failure.
+ if (!error.Success()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() failed to launch process: "
+ "%s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ }
- // Return the process and process id to the caller through the launch args.
- native_process_sp = np_darwin_sp;
+ // Handle failure to return a pid.
+ if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() launch succeeded but no "
+ "pid was returned! Aborting.",
+ __FUNCTION__);
return error;
-}
+ }
+
+ // Create the Darwin native process impl.
+ std::shared_ptr<NativeProcessDarwin> np_darwin_sp(
+ new NativeProcessDarwin(launch_info.GetProcessID(), pty_master_fd));
+ if (!np_darwin_sp->RegisterNativeDelegate(native_delegate)) {
+ native_process_sp.reset();
+ error.SetErrorStringWithFormat("failed to register the native delegate");
+ return error;
+ }
-Error
-NativeProcessProtocol::Attach(lldb::pid_t pid,
- NativeProcessProtocol::NativeDelegate
- &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &native_process_sp)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ // Finalize the processing needed to debug the launched process with
+ // a NativeProcessDarwin instance.
+ error = np_darwin_sp->FinalizeLaunch(launch_flavor, mainloop);
+ if (!error.Success()) {
if (log)
- log->Printf ("NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__,
- pid);
+ log->Printf("NativeProcessDarwin::%s() aborting, failed to finalize"
+ " the launching of the process: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ }
- // Retrieve the architecture for the running process.
- ArchSpec process_arch;
- Error error = ResolveProcessArchitecture(pid, process_arch);
- if (!error.Success())
- return error;
+ // Return the process and process id to the caller through the launch args.
+ native_process_sp = np_darwin_sp;
+ return error;
+}
- // TODO get attach to return this value.
- const int pty_master_fd = -1;
- std::shared_ptr<NativeProcessDarwin> native_process_darwin_sp(
- new NativeProcessDarwin(pid, pty_master_fd));
+Error NativeProcessProtocol::Attach(
+ lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
+ MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__,
+ pid);
+
+ // Retrieve the architecture for the running process.
+ ArchSpec process_arch;
+ Error error = ResolveProcessArchitecture(pid, process_arch);
+ if (!error.Success())
+ return error;
- if (!native_process_darwin_sp->RegisterNativeDelegate(native_delegate))
- {
- error.SetErrorStringWithFormat("failed to register the native "
- "delegate");
- return error;
- }
+ // TODO get attach to return this value.
+ const int pty_master_fd = -1;
+ std::shared_ptr<NativeProcessDarwin> native_process_darwin_sp(
+ new NativeProcessDarwin(pid, pty_master_fd));
- native_process_darwin_sp->AttachToInferior(mainloop, pid, error);
- if (!error.Success())
- return error;
+ if (!native_process_darwin_sp->RegisterNativeDelegate(native_delegate)) {
+ error.SetErrorStringWithFormat("failed to register the native "
+ "delegate");
+ return error;
+ }
- native_process_sp = native_process_darwin_sp;
+ native_process_darwin_sp->AttachToInferior(mainloop, pid, error);
+ if (!error.Success())
return error;
+
+ native_process_sp = native_process_darwin_sp;
+ return error;
}
// -----------------------------------------------------------------------------
// ctor/dtor
// -----------------------------------------------------------------------------
-NativeProcessDarwin::NativeProcessDarwin(lldb::pid_t pid, int pty_master_fd) :
- NativeProcessProtocol(pid),
- m_task(TASK_NULL),
- m_did_exec(false),
- m_cpu_type(0),
- m_exception_port(MACH_PORT_NULL),
- m_exc_port_info(),
- m_exception_thread(nullptr),
- m_exception_messages_mutex(),
- m_sent_interrupt_signo(0),
- m_auto_resume_signo(0),
- m_thread_list(),
- m_thread_actions(),
- m_waitpid_pipe(),
- m_waitpid_thread(nullptr),
- m_waitpid_reader_handle()
-{
- // TODO add this to the NativeProcessProtocol constructor.
- m_terminal_fd = pty_master_fd;
+NativeProcessDarwin::NativeProcessDarwin(lldb::pid_t pid, int pty_master_fd)
+ : NativeProcessProtocol(pid), m_task(TASK_NULL), m_did_exec(false),
+ m_cpu_type(0), m_exception_port(MACH_PORT_NULL), m_exc_port_info(),
+ m_exception_thread(nullptr), m_exception_messages_mutex(),
+ m_sent_interrupt_signo(0), m_auto_resume_signo(0), m_thread_list(),
+ m_thread_actions(), m_waitpid_pipe(), m_waitpid_thread(nullptr),
+ m_waitpid_reader_handle() {
+ // TODO add this to the NativeProcessProtocol constructor.
+ m_terminal_fd = pty_master_fd;
}
-NativeProcessDarwin::~NativeProcessDarwin()
-{
-}
+NativeProcessDarwin::~NativeProcessDarwin() {}
// -----------------------------------------------------------------------------
// Instance methods
// -----------------------------------------------------------------------------
-Error
-NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
- MainLoop &main_loop)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+Error NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
+ MainLoop &main_loop) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
#if 0
m_path = path;
@@ -213,772 +185,680 @@ NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
m_args.push_back(arg);
#endif
- error = StartExceptionThread();
- if (!error.Success())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failure starting the "
- "mach exception port monitor thread: %s",
- __FUNCTION__, error.AsCString());
+ error = StartExceptionThread();
+ if (!error.Success()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): failure starting the "
+ "mach exception port monitor thread: %s",
+ __FUNCTION__, error.AsCString());
- // Terminate the inferior process. There's nothing meaningful we can
- // do if we can't receive signals and exceptions. Since we launched
- // the process, it's fair game for us to kill it.
- ::ptrace(PT_KILL, m_pid, 0, 0);
- SetState(eStateExited);
+ // Terminate the inferior process. There's nothing meaningful we can
+ // do if we can't receive signals and exceptions. Since we launched
+ // the process, it's fair game for us to kill it.
+ ::ptrace(PT_KILL, m_pid, 0, 0);
+ SetState(eStateExited);
- return error;
+ return error;
+ }
+
+ StartSTDIOThread();
+
+ if (launch_flavor == LaunchFlavor::PosixSpawn) {
+ SetState(eStateAttaching);
+ errno = 0;
+ int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0);
+ if (err == 0) {
+ // m_flags |= eMachProcessFlagsAttached;
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): successfully spawned "
+ "process with pid %" PRIu64,
+ __FUNCTION__, m_pid);
+ } else {
+ error.SetErrorToErrno();
+ SetState(eStateExited);
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): error: failed to "
+ "attach to spawned pid %" PRIu64 " (error=%d (%s))",
+ __FUNCTION__, m_pid, (int)error.GetError(),
+ error.AsCString());
+ return error;
}
+ }
- StartSTDIOThread();
-
- if (launch_flavor == LaunchFlavor::PosixSpawn)
- {
- SetState(eStateAttaching);
- errno = 0;
- int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0);
- if (err == 0)
- {
- // m_flags |= eMachProcessFlagsAttached;
- if (log)
- log->Printf("NativeProcessDarwin::%s(): successfully spawned "
- "process with pid %" PRIu64, __FUNCTION__, m_pid);
- }
- else
- {
- error.SetErrorToErrno();
- SetState(eStateExited);
- if (log)
- log->Printf("NativeProcessDarwin::%s(): error: failed to "
- "attach to spawned pid %" PRIu64 " (error=%d (%s))",
- __FUNCTION__, m_pid, (int)error.GetError(),
- error.AsCString());
- return error;
- }
- }
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): new pid is %" PRIu64 "...",
+ __FUNCTION__, m_pid);
+ // Spawn a thread to reap our child inferior process...
+ error = StartWaitpidThread(main_loop);
+ if (error.Fail()) {
if (log)
- log->Printf("NativeProcessDarwin::%s(): new pid is %" PRIu64 "...",
- __FUNCTION__, m_pid);
-
- // Spawn a thread to reap our child inferior process...
- error = StartWaitpidThread(main_loop);
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failed to start waitpid() "
- "thread: %s", __FUNCTION__, error.AsCString());
- kill(SIGKILL, static_cast<::pid_t>(m_pid));
- return error;
- }
+ log->Printf("NativeProcessDarwin::%s(): failed to start waitpid() "
+ "thread: %s",
+ __FUNCTION__, error.AsCString());
+ kill(SIGKILL, static_cast<::pid_t>(m_pid));
+ return error;
+ }
- if (TaskPortForProcessID(error) == 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.
- if (log)
- log->Printf("NativeProcessDarwin::%s(): could not get task port "
- "for process, sending SIGKILL and exiting: %s",
- __FUNCTION__, error.AsCString());
- kill(SIGKILL, static_cast<::pid_t>(m_pid));
- return error;
- }
+ if (TaskPortForProcessID(error) == 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.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): could not get task port "
+ "for process, sending SIGKILL and exiting: %s",
+ __FUNCTION__, error.AsCString());
+ kill(SIGKILL, static_cast<::pid_t>(m_pid));
+ return error;
+ }
- // Indicate that we're stopped, as we always launch suspended.
- SetState(eStateStopped);
+ // Indicate that we're stopped, as we always launch suspended.
+ SetState(eStateStopped);
- // Success.
- return error;
+ // Success.
+ return error;
}
-Error
-NativeProcessDarwin::SaveExceptionPortInfo()
-{
- return m_exc_port_info.Save(m_task);
+Error NativeProcessDarwin::SaveExceptionPortInfo() {
+ return m_exc_port_info.Save(m_task);
}
-bool
-NativeProcessDarwin::ProcessUsingSpringBoard() const
-{
- // TODO implement flags
- // return (m_flags & eMachProcessFlagsUsingSBS) != 0;
- return false;
+bool NativeProcessDarwin::ProcessUsingSpringBoard() const {
+ // TODO implement flags
+ // return (m_flags & eMachProcessFlagsUsingSBS) != 0;
+ return false;
}
-bool
-NativeProcessDarwin::ProcessUsingBackBoard() const
-{
- // TODO implement flags
- // return (m_flags & eMachProcessFlagsUsingBKS) != 0;
- return false;
+bool NativeProcessDarwin::ProcessUsingBackBoard() const {
+ // TODO implement flags
+ // return (m_flags & eMachProcessFlagsUsingBKS) != 0;
+ 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
-NativeProcessDarwin::ExceptionMessageReceived(const MachException::Message&
- message)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
-
- std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
- if (m_exception_messages.empty())
- {
- // Suspend the task the moment we receive our first exception message.
- SuspendTask();
- }
-
- // 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(message);
-
- if (log)
- log->Printf("NativeProcessDarwin::%s(): new queued message count: %lu",
- __FUNCTION__, m_exception_messages.size());
+void NativeProcessDarwin::ExceptionMessageReceived(
+ const MachException::Message &message) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+
+ std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
+ if (m_exception_messages.empty()) {
+ // Suspend the task the moment we receive our first exception message.
+ SuspendTask();
+ }
+
+ // 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(message);
+
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): new queued message count: %lu",
+ __FUNCTION__, m_exception_messages.size());
}
-void*
-NativeProcessDarwin::ExceptionThread(void *arg)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
- if (!arg)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): cannot run mach exception "
- "thread, mandatory process arg was null", __FUNCTION__);
- return nullptr;
- }
+void *NativeProcessDarwin::ExceptionThread(void *arg) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+ if (!arg) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): cannot run mach exception "
+ "thread, mandatory process arg was null",
+ __FUNCTION__);
+ return nullptr;
+ }
- return reinterpret_cast<NativeProcessDarwin*>(arg)->DoExceptionThread();
+ return reinterpret_cast<NativeProcessDarwin *>(arg)->DoExceptionThread();
}
-void*
-NativeProcessDarwin::DoExceptionThread()
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
-
+void *NativeProcessDarwin::DoExceptionThread() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(arg=%p) starting thread...",
+ __FUNCTION__, this);
+
+ pthread_setname_np("exception monitoring thread");
+
+ // Ensure we don't get CPU starved.
+ MaybeRaiseThreadPriority();
+
+ // We keep a count of the number of consecutive exceptions received so
+ // we know to grab all exceptions without a timeout. 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 loop in this
+ // thread can stop periodically if needed to service things related to this
+ // process.
+ //
+ // [did we lose some words here?]
+ //
+ // flag set in the options, so we will wait forever for an exception on
+ // 0 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.
+ //
+ // We choose to park a thread on this, rather than polling, because the
+ // polling is expensive. On devices, we need to minimize overhead caused
+ // by the process monitor.
+ uint32_t num_exceptions_received = 0;
+ Error error;
+ task_t task = m_task;
+ mach_msg_timeout_t periodic_timeout = 0;
+
+#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS)
+ mach_msg_timeout_t watchdog_elapsed = 0;
+ mach_msg_timeout_t watchdog_timeout = 60 * 1000;
+ ::pid_t pid = (::pid_t)process->GetID();
+ CFReleaser<SBSWatchdogAssertionRef> watchdog;
+
+ if (process->ProcessUsingSpringBoard()) {
+ // Request a renewal for every 60 seconds if we attached using
+ // SpringBoard.
+ watchdog.reset(::SBSWatchdogAssertionCreateForPID(nullptr, pid, 60));
if (log)
- log->Printf("NativeProcessDarwin::%s(arg=%p) starting thread...",
- __FUNCTION__, this);
-
- pthread_setname_np("exception monitoring thread");
-
- // Ensure we don't get CPU starved.
- MaybeRaiseThreadPriority();
-
- // We keep a count of the number of consecutive exceptions received so
- // we know to grab all exceptions without a timeout. 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 loop in this
- // thread can stop periodically if needed to service things related to this
- // process.
- //
- // [did we lose some words here?]
- //
- // flag set in the options, so we will wait forever for an exception on
- //0 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.
- //
- // We choose to park a thread on this, rather than polling, because the
- // polling is expensive. On devices, we need to minimize overhead caused
- // by the process monitor.
- uint32_t num_exceptions_received = 0;
- Error error;
- task_t task = m_task;
- mach_msg_timeout_t periodic_timeout = 0;
-
-#if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)
- mach_msg_timeout_t watchdog_elapsed = 0;
- mach_msg_timeout_t watchdog_timeout = 60 * 1000;
- ::pid_t pid = (::pid_t)process->GetID();
- CFReleaser<SBSWatchdogAssertionRef> watchdog;
-
- if (process->ProcessUsingSpringBoard())
- {
- // Request a renewal for every 60 seconds if we attached using
- // SpringBoard.
- watchdog.reset(::SBSWatchdogAssertionCreateForPID(nullptr, pid, 60));
- if (log)
- log->Printf("::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) "
- "=> %p", pid, watchdog.get());
-
- if (watchdog.get())
- {
- ::SBSWatchdogAssertionRenew (watchdog.get());
-
- CFTimeInterval watchdogRenewalInterval =
- ::SBSWatchdogAssertionGetRenewalInterval (watchdog.get());
- if (log)
- log->Printf("::SBSWatchdogAssertionGetRenewalInterval(%p) => "
- "%g seconds", watchdog.get(),
- watchdogRenewalInterval);
- if (watchdogRenewalInterval > 0.0)
- {
- watchdog_timeout =
- (mach_msg_timeout_t)watchdogRenewalInterval * 1000;
- if (watchdog_timeout > 3000)
- {
- // Give us a second to renew our timeout.
- watchdog_timeout -= 1000;
- }
- else if (watchdog_timeout > 1000)
- {
- // Give us a quarter of a second to renew our timeout.
- watchdog_timeout -= 250;
- }
- }
+ log->Printf("::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) "
+ "=> %p",
+ pid, watchdog.get());
+
+ if (watchdog.get()) {
+ ::SBSWatchdogAssertionRenew(watchdog.get());
+
+ CFTimeInterval watchdogRenewalInterval =
+ ::SBSWatchdogAssertionGetRenewalInterval(watchdog.get());
+ if (log)
+ log->Printf("::SBSWatchdogAssertionGetRenewalInterval(%p) => "
+ "%g seconds",
+ watchdog.get(), watchdogRenewalInterval);
+ if (watchdogRenewalInterval > 0.0) {
+ watchdog_timeout = (mach_msg_timeout_t)watchdogRenewalInterval * 1000;
+ if (watchdog_timeout > 3000) {
+ // Give us a second to renew our timeout.
+ watchdog_timeout -= 1000;
+ } else if (watchdog_timeout > 1000) {
+ // Give us a quarter of a second to renew our timeout.
+ watchdog_timeout -= 250;
}
- if (periodic_timeout == 0 || periodic_timeout > watchdog_timeout)
- periodic_timeout = watchdog_timeout;
+ }
}
-#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)
+ if (periodic_timeout == 0 || periodic_timeout > watchdog_timeout)
+ periodic_timeout = watchdog_timeout;
+ }
+#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)
#ifdef WITH_BKS
- CFReleaser<BKSWatchdogAssertionRef> watchdog;
- if (process->ProcessUsingBackBoard())
- {
- ::pid_t pid = process->GetID();
- CFAllocatorRef alloc = kCFAllocatorDefault;
- watchdog.reset(::BKSWatchdogAssertionCreateForPID(alloc, pid));
- }
+ CFReleaser<BKSWatchdogAssertionRef> watchdog;
+ if (process->ProcessUsingBackBoard()) {
+ ::pid_t pid = process->GetID();
+ CFAllocatorRef alloc = kCFAllocatorDefault;
+ watchdog.reset(::BKSWatchdogAssertionCreateForPID(alloc, pid));
+ }
#endif // #ifdef WITH_BKS
- // Do we want to use a weak pointer to the NativeProcessDarwin here, in
- // which case we can guarantee we don't whack the process monitor if we
- // race between this thread and the main one on shutdown?
- while (IsExceptionPortValid())
- {
- ::pthread_testcancel();
-
- MachException::Message exception_message;
-
- if (num_exceptions_received > 0)
- {
- // We don't want a timeout here, just receive as many exceptions as
- // we can since we already have one. We want to get all currently
- // available exceptions for this task at once.
- error = exception_message.Receive(GetExceptionPort(),
- MACH_RCV_MSG | MACH_RCV_INTERRUPT
- | MACH_RCV_TIMEOUT, 0);
+ // Do we want to use a weak pointer to the NativeProcessDarwin here, in
+ // which case we can guarantee we don't whack the process monitor if we
+ // race between this thread and the main one on shutdown?
+ while (IsExceptionPortValid()) {
+ ::pthread_testcancel();
+
+ MachException::Message exception_message;
+
+ if (num_exceptions_received > 0) {
+ // We don't want a timeout here, just receive as many exceptions as
+ // we can since we already have one. We want to get all currently
+ // available exceptions for this task at once.
+ error = exception_message.Receive(
+ GetExceptionPort(),
+ MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, 0);
+ } else if (periodic_timeout > 0) {
+ // We need to stop periodically in this loop, so try and get a mach
+ // message with a valid timeout (ms).
+ error = exception_message.Receive(GetExceptionPort(),
+ MACH_RCV_MSG | MACH_RCV_INTERRUPT |
+ MACH_RCV_TIMEOUT,
+ periodic_timeout);
+ } else {
+ // We don't need to parse all current exceptions or stop
+ // periodically, just wait for an exception forever.
+ error = exception_message.Receive(GetExceptionPort(),
+ MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0);
+ }
+
+ if (error.Success()) {
+ // We successfully received an exception.
+ if (exception_message.CatchExceptionRaise(task)) {
+ ++num_exceptions_received;
+ ExceptionMessageReceived(exception_message);
+ }
+ } else {
+ if (error.GetError() == MACH_RCV_INTERRUPTED) {
+ // We were interrupted.
+
+ // If we have no task port we should exit this thread, as it implies
+ // the inferior went down.
+ if (!IsExceptionPortValid()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): the inferior "
+ "exception port is no longer valid, "
+ "canceling exception thread...",
+ __FUNCTION__);
+ // Should we be setting a process state here?
+ break;
}
- else if (periodic_timeout > 0)
- {
- // We need to stop periodically in this loop, so try and get a mach
- // message with a valid timeout (ms).
- error = exception_message.Receive(GetExceptionPort(),
- MACH_RCV_MSG | MACH_RCV_INTERRUPT
- | MACH_RCV_TIMEOUT,
- periodic_timeout);
+
+ // Make sure the inferior task is still valid.
+ if (IsTaskValid()) {
+ // Task is still ok.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): interrupted, but "
+ "the inferior task iss till valid, "
+ "continuing...",
+ __FUNCTION__);
+ continue;
+ } else {
+ // The inferior task is no longer valid. Time to exit as
+ // the process has gone away.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): the inferior task "
+ "has exited, and so will we...",
+ __FUNCTION__);
+ // Does this race at all with our waitpid()?
+ SetState(eStateExited);
+ break;
}
- else
- {
- // We don't need to parse all current exceptions or stop
- // periodically, just wait for an exception forever.
- error = exception_message.Receive(GetExceptionPort(),
- MACH_RCV_MSG | MACH_RCV_INTERRUPT,
- 0);
+ } else if (error.GetError() == MACH_RCV_TIMED_OUT) {
+ // We timed out when waiting for exceptions.
+
+ if (num_exceptions_received > 0) {
+ // We were receiving all current exceptions with a timeout of
+ // zero. It is time to go back to our normal looping mode.
+ num_exceptions_received = 0;
+
+ // Notify our main thread we have a complete exception message
+ // bundle available. Get the possibly updated task port back
+ // from the process in case we exec'ed and our task port
+ // changed.
+ task = ExceptionMessageBundleComplete();
+
+ // In case we use a timeout value when getting exceptions,
+ // make sure our task is still valid.
+ if (IsTaskValid(task)) {
+ // Task is still ok.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): got a timeout, "
+ "continuing...",
+ __FUNCTION__);
+ continue;
+ } else {
+ // The inferior task is no longer valid. Time to exit as
+ // the process has gone away.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): the inferior "
+ "task has exited, and so will we...",
+ __FUNCTION__);
+ // Does this race at all with our waitpid()?
+ SetState(eStateExited);
+ break;
+ }
}
- if (error.Success())
- {
- // We successfully received an exception.
- if (exception_message.CatchExceptionRaise(task))
- {
- ++num_exceptions_received;
- ExceptionMessageReceived(exception_message);
- }
+#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS)
+ if (watchdog.get()) {
+ watchdog_elapsed += periodic_timeout;
+ if (watchdog_elapsed >= watchdog_timeout) {
+ if (log)
+ log->Printf("SBSWatchdogAssertionRenew(%p)", watchdog.get());
+ ::SBSWatchdogAssertionRenew(watchdog.get());
+ watchdog_elapsed = 0;
+ }
}
- else
- {
- if (error.GetError() == MACH_RCV_INTERRUPTED)
- {
- // We were interrupted.
-
- // If we have no task port we should exit this thread, as it implies
- // the inferior went down.
- if (!IsExceptionPortValid())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): the inferior "
- "exception port is no longer valid, "
- "canceling exception thread...", __FUNCTION__);
- // Should we be setting a process state here?
- break;
- }
-
- // Make sure the inferior task is still valid.
- if (IsTaskValid())
- {
- // Task is still ok.
- if (log)
- log->Printf("NativeProcessDarwin::%s(): interrupted, but "
- "the inferior task iss till valid, "
- "continuing...", __FUNCTION__);
- continue;
- }
- else
- {
- // The inferior task is no longer valid. Time to exit as
- // the process has gone away.
- if (log)
- log->Printf("NativeProcessDarwin::%s(): the inferior task "
- "has exited, and so will we...", __FUNCTION__);
- // Does this race at all with our waitpid()?
- SetState(eStateExited);
- break;
- }
- }
- else if (error.GetError() == MACH_RCV_TIMED_OUT)
- {
- // We timed out when waiting for exceptions.
-
- if (num_exceptions_received > 0)
- {
- // We were receiving all current exceptions with a timeout of
- // zero. It is time to go back to our normal looping mode.
- num_exceptions_received = 0;
-
- // Notify our main thread we have a complete exception message
- // bundle available. Get the possibly updated task port back
- // from the process in case we exec'ed and our task port
- // changed.
- task = ExceptionMessageBundleComplete();
-
- // In case we use a timeout value when getting exceptions,
- // make sure our task is still valid.
- if (IsTaskValid(task))
- {
- // Task is still ok.
- if (log)
- log->Printf("NativeProcessDarwin::%s(): got a timeout, "
- "continuing...", __FUNCTION__);
- continue;
- }
- else
- {
- // The inferior task is no longer valid. Time to exit as
- // the process has gone away.
- if (log)
- log->Printf("NativeProcessDarwin::%s(): the inferior "
- "task has exited, and so will we...",
- __FUNCTION__);
- // Does this race at all with our waitpid()?
- SetState(eStateExited);
- break;
- }
- }
-
-#if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)
- if (watchdog.get())
- {
- watchdog_elapsed += periodic_timeout;
- if (watchdog_elapsed >= watchdog_timeout)
- {
- if (log)
- log->Printf("SBSWatchdogAssertionRenew(%p)",
- watchdog.get());
- ::SBSWatchdogAssertionRenew (watchdog.get());
- watchdog_elapsed = 0;
- }
- }
#endif
- }
- else
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): continuing after "
- "receiving an unexpected error: %u (%s)",
- __FUNCTION__, error.GetError(), error.AsCString());
- // TODO: notify of error?
- }
- }
- }
-
-#if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)
- if (watchdog.get())
- {
- // TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel when we
- // all are up and running on systems that support it. The SBS framework has a #define
- // that will forward SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel for now
- // so it should still build either way.
- DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionRelease(%p)", watchdog.get());
- ::SBSWatchdogAssertionRelease (watchdog.get());
+ } else {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): continuing after "
+ "receiving an unexpected error: %u (%s)",
+ __FUNCTION__, error.GetError(), error.AsCString());
+ // TODO: notify of error?
+ }
}
-#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)
-
- if (log)
- log->Printf("NativeProcessDarwin::%s(%p): thread exiting...",
- __FUNCTION__, this);
- return nullptr;
+ }
+
+#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS)
+ if (watchdog.get()) {
+ // TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel
+ // when we
+ // all are up and running on systems that support it. The SBS framework has
+ // a #define
+ // that will forward SBSWatchdogAssertionRelease to
+ // SBSWatchdogAssertionCancel for now
+ // so it should still build either way.
+ DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionRelease(%p)",
+ watchdog.get());
+ ::SBSWatchdogAssertionRelease(watchdog.get());
+ }
+#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)
+
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(%p): thread exiting...", __FUNCTION__,
+ this);
+ return nullptr;
}
-Error
-NativeProcessDarwin::StartExceptionThread()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__);
-
- // Make sure we've looked up the inferior port.
- TaskPortForProcessID(error);
+Error NativeProcessDarwin::StartExceptionThread() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__);
- // Ensure the inferior task is valid.
- if (!IsTaskValid())
- {
- error.SetErrorStringWithFormat("cannot start exception thread: "
- "task 0x%4.4x is not valid", m_task);
- return error;
- }
+ // Make sure we've looked up the inferior port.
+ TaskPortForProcessID(error);
- // Get the mach port for the process monitor.
- mach_port_t task_self = mach_task_self();
+ // Ensure the inferior task is valid.
+ if (!IsTaskValid()) {
+ error.SetErrorStringWithFormat("cannot start exception thread: "
+ "task 0x%4.4x is not valid",
+ m_task);
+ return error;
+ }
- // Allocate an exception port that we will use to track our child process
- auto mach_err = ::mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE,
- &m_exception_port);
- error.SetError(mach_err, eErrorTypeMachKernel);
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): mach_port_allocate("
- "task_self=0x%4.4x, MACH_PORT_RIGHT_RECEIVE, "
- "&m_exception_port) failed: %u (%s)", __FUNCTION__,
- task_self, error.GetError(), error.AsCString());
- return error;
- }
+ // Get the mach port for the process monitor.
+ mach_port_t task_self = mach_task_self();
- // Add the ability to send messages on the new exception port
- mach_err = ::mach_port_insert_right(task_self, m_exception_port,
- m_exception_port, MACH_MSG_TYPE_MAKE_SEND);
- error.SetError(mach_err, eErrorTypeMachKernel);
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): mach_port_insert_right("
- "task_self=0x%4.4x, m_exception_port=0x%4.4x, "
- "m_exception_port=0x%4.4x, MACH_MSG_TYPE_MAKE_SEND) "
- "failed: %u (%s)", __FUNCTION__,
- task_self, m_exception_port, m_exception_port,
- error.GetError(), error.AsCString());
- return error;
- }
+ // Allocate an exception port that we will use to track our child process
+ auto mach_err = ::mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE,
+ &m_exception_port);
+ error.SetError(mach_err, eErrorTypeMachKernel);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): mach_port_allocate("
+ "task_self=0x%4.4x, MACH_PORT_RIGHT_RECEIVE, "
+ "&m_exception_port) failed: %u (%s)",
+ __FUNCTION__, task_self, error.GetError(), error.AsCString());
+ return error;
+ }
- // Save the original state of the exception ports for our child process.
- error = SaveExceptionPortInfo();
- if (error.Fail() || (m_exc_port_info.mask == 0))
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): SaveExceptionPortInfo() "
- "failed, cannot install exception handler: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
+ // Add the ability to send messages on the new exception port
+ mach_err = ::mach_port_insert_right(
+ task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND);
+ error.SetError(mach_err, eErrorTypeMachKernel);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): mach_port_insert_right("
+ "task_self=0x%4.4x, m_exception_port=0x%4.4x, "
+ "m_exception_port=0x%4.4x, MACH_MSG_TYPE_MAKE_SEND) "
+ "failed: %u (%s)",
+ __FUNCTION__, task_self, m_exception_port, m_exception_port,
+ error.GetError(), error.AsCString());
+ return error;
+ }
- // Set the ability to get all exceptions on this port.
- mach_err = ::task_set_exception_ports(m_task, m_exc_port_info.mask,
- m_exception_port,
- EXCEPTION_DEFAULT |
- MACH_EXCEPTION_CODES,
- THREAD_STATE_NONE);
- error.SetError(mach_err, eErrorTypeMachKernel);
- if (error.Fail())
- {
- if (log)
- log->Printf("::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) failed: "
- "%u (%s)", m_task, m_exc_port_info.mask,
- m_exception_port, (EXCEPTION_DEFAULT |
- MACH_EXCEPTION_CODES),
- THREAD_STATE_NONE, error.GetError(),
- error.AsCString());
- return error;
- }
+ // Save the original state of the exception ports for our child process.
+ error = SaveExceptionPortInfo();
+ if (error.Fail() || (m_exc_port_info.mask == 0)) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): SaveExceptionPortInfo() "
+ "failed, cannot install exception handler: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ }
+
+ // Set the ability to get all exceptions on this port.
+ mach_err = ::task_set_exception_ports(
+ m_task, m_exc_port_info.mask, m_exception_port,
+ EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
+ error.SetError(mach_err, eErrorTypeMachKernel);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("::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) failed: "
+ "%u (%s)",
+ m_task, m_exc_port_info.mask, m_exception_port,
+ (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), THREAD_STATE_NONE,
+ error.GetError(), error.AsCString());
+ return error;
+ }
- // Create the exception thread.
- auto pthread_err = ::pthread_create(&m_exception_thread, nullptr,
- ExceptionThread, this);
- error.SetError(pthread_err, eErrorTypePOSIX);
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failed to create Mach "
- "exception-handling thread: %u (%s)", __FUNCTION__,
- error.GetError(), error.AsCString());
- }
+ // Create the exception thread.
+ auto pthread_err =
+ ::pthread_create(&m_exception_thread, nullptr, ExceptionThread, this);
+ error.SetError(pthread_err, eErrorTypePOSIX);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): failed to create Mach "
+ "exception-handling thread: %u (%s)",
+ __FUNCTION__, error.GetError(), error.AsCString());
+ }
- return error;
+ return error;
}
lldb::addr_t
-NativeProcessDarwin::GetDYLDAllImageInfosAddress(Error &error) const
-{
- error.Clear();
-
- struct hack_task_dyld_info dyld_info;
- mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
- // Make sure that COUNT isn't bigger than our hacked up struct
- // hack_task_dyld_info. If it is, then make COUNT smaller to match.
- if (count > (sizeof(struct hack_task_dyld_info) / sizeof(natural_t)))
- {
- count = (sizeof(struct hack_task_dyld_info) / sizeof(natural_t));
- }
-
- TaskPortForProcessID(error);
- if (error.Fail())
- return LLDB_INVALID_ADDRESS;
+NativeProcessDarwin::GetDYLDAllImageInfosAddress(Error &error) const {
+ error.Clear();
+
+ struct hack_task_dyld_info dyld_info;
+ mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
+ // Make sure that COUNT isn't bigger than our hacked up struct
+ // hack_task_dyld_info. If it is, then make COUNT smaller to match.
+ if (count > (sizeof(struct hack_task_dyld_info) / sizeof(natural_t))) {
+ count = (sizeof(struct hack_task_dyld_info) / sizeof(natural_t));
+ }
+
+ TaskPortForProcessID(error);
+ if (error.Fail())
+ return LLDB_INVALID_ADDRESS;
- auto mach_err = ::task_info(m_task, TASK_DYLD_INFO, (task_info_t)&dyld_info,
- &count);
- error.SetError(mach_err, eErrorTypeMachKernel);
- if (error.Success())
- {
- // We now have the address of the all image infos structure.
- return dyld_info.all_image_info_addr;
- }
+ auto mach_err =
+ ::task_info(m_task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
+ error.SetError(mach_err, eErrorTypeMachKernel);
+ if (error.Success()) {
+ // We now have the address of the all image infos structure.
+ return dyld_info.all_image_info_addr;
+ }
- // We don't have it.
- return LLDB_INVALID_ADDRESS;
+ // We don't have it.
+ return LLDB_INVALID_ADDRESS;
}
-uint32_t
-NativeProcessDarwin::GetCPUTypeForLocalProcess(::pid_t pid)
-{
- int mib[CTL_MAXNAME] = {0, };
- size_t len = CTL_MAXNAME;
+uint32_t NativeProcessDarwin::GetCPUTypeForLocalProcess(::pid_t pid) {
+ int mib[CTL_MAXNAME] = {
+ 0,
+ };
+ size_t len = CTL_MAXNAME;
- if (::sysctlnametomib("sysctl.proc_cputype", mib, &len))
- return 0;
+ if (::sysctlnametomib("sysctl.proc_cputype", mib, &len))
+ return 0;
- mib[len] = pid;
- len++;
+ 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;
+ 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;
}
-uint32_t
-NativeProcessDarwin::GetCPUType() const
-{
- if (m_cpu_type == 0 && m_pid != 0)
- m_cpu_type = GetCPUTypeForLocalProcess(m_pid);
- return m_cpu_type;
+uint32_t NativeProcessDarwin::GetCPUType() const {
+ if (m_cpu_type == 0 && m_pid != 0)
+ m_cpu_type = GetCPUTypeForLocalProcess(m_pid);
+ return m_cpu_type;
}
-task_t
-NativeProcessDarwin::ExceptionMessageBundleComplete()
-{
- // We have a complete bundle of exceptions for our child process.
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
-
- std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
- if (log)
- log->Printf("NativeProcessDarwin::%s(): processing %lu exception "
- "messages.", __FUNCTION__, m_exception_messages.size());
-
- if (m_exception_messages.empty())
- {
- // Not particularly useful...
- return m_task;
- }
-
- bool auto_resume = false;
- m_did_exec = false;
+task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
+ // We have a complete bundle of exceptions for our child process.
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
- // First check for any SIGTRAP and make sure we didn't exec
- const task_t task = m_task;
- 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)
- {
- // This is an exception that is not for our inferior, ignore.
- continue;
- }
-
- // This is an exception for the inferior.
- ++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 addr_t aii_addr =
- GetDYLDAllImageInfosAddress(error);
- if (aii_addr == LLDB_INVALID_ADDRESS)
- break;
-
- const addr_t info_array_count_addr = aii_addr + 4;
- uint32_t info_array_count = 0;
- size_t bytes_read = 0;
- Error read_error;
- read_error = ReadMemory(info_array_count_addr, // source addr
- &info_array_count, // dest addr
- 4, // byte count
- bytes_read); // #bytes read
- if (read_error.Success() && (bytes_read == 4))
- {
- if (info_array_count == 0)
- {
- // We got the all infos address, and there are zero
- // entries. We think we exec'd.
- m_did_exec = true;
-
- // Force the task port to update itself in case the
- // task port changed after exec
- const task_t old_task = m_task;
- const bool force_update = true;
- const task_t new_task =
- TaskPortForProcessID(error, force_update);
- if (old_task != new_task)
- {
- if (log)
- log->Printf("exec: inferior task port changed "
- "from 0x%4.4x to 0x%4.4x", old_task,
- new_task);
- }
- }
- }
- else
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s() warning: "
- "failed to read all_image_infos."
- "infoArrayCount from 0x%8.8llx",
- __FUNCTION__, info_array_count_addr);
- }
- }
- else if ((m_sent_interrupt_signo != 0) &&
- (signo == m_sent_interrupt_signo))
- {
- // We just received the interrupt that we sent to ourselves.
- received_interrupt = true;
- }
- }
-
- if (m_did_exec)
- {
- cpu_type_t process_cpu_type = GetCPUTypeForLocalProcess(m_pid);
- if (m_cpu_type != process_cpu_type)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): arch changed from "
- "0x%8.8x to 0x%8.8x", __FUNCTION__, m_cpu_type,
- process_cpu_type);
- m_cpu_type = process_cpu_type;
- // TODO figure out if we need to do something here.
- // DNBArchProtocol::SetArchitecture (process_cpu_type);
- }
- m_thread_list.Clear();
+ std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): processing %lu exception "
+ "messages.",
+ __FUNCTION__, m_exception_messages.size());
- // TODO hook up breakpoints.
- // m_breakpoints.DisableAll();
- }
-
- if (m_sent_interrupt_signo != 0)
- {
- if (received_interrupt)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): process "
- "successfully interrupted with signal %i",
- __FUNCTION__, m_sent_interrupt_signo);
-
- // Mark that we received the interrupt signal
- m_sent_interrupt_signo = 0;
- // Now check if we had a case where:
- // 1 - We called NativeProcessDarwin::Interrupt() but we stopped
- // for another reason.
- // 2 - We called NativeProcessDarwin::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;
- if (log)
- log->Printf("NativeProcessDarwin::%s(): auto "
- "resuming due to unhandled interrupt "
- "signal %i", __FUNCTION__,
- m_auto_resume_signo);
- }
- m_auto_resume_signo = 0;
- }
- }
- else
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): didn't get signal "
- "%i after MachProcess::Interrupt()",
- __FUNCTION__, m_sent_interrupt_signo);
+ if (m_exception_messages.empty()) {
+ // Not particularly useful...
+ return m_task;
+ }
+
+ bool auto_resume = false;
+ m_did_exec = false;
+
+ // First check for any SIGTRAP and make sure we didn't exec
+ const task_t task = m_task;
+ 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) {
+ // This is an exception that is not for our inferior, ignore.
+ continue;
+ }
+
+ // This is an exception for the inferior.
+ ++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 addr_t aii_addr = GetDYLDAllImageInfosAddress(error);
+ if (aii_addr == LLDB_INVALID_ADDRESS)
+ break;
+
+ const addr_t info_array_count_addr = aii_addr + 4;
+ uint32_t info_array_count = 0;
+ size_t bytes_read = 0;
+ Error read_error;
+ read_error = ReadMemory(info_array_count_addr, // source addr
+ &info_array_count, // dest addr
+ 4, // byte count
+ bytes_read); // #bytes read
+ if (read_error.Success() && (bytes_read == 4)) {
+ if (info_array_count == 0) {
+ // We got the all infos address, and there are zero
+ // entries. We think we exec'd.
+ m_did_exec = true;
+
+ // Force the task port to update itself in case the
+ // task port changed after exec
+ const task_t old_task = m_task;
+ const bool force_update = true;
+ const task_t new_task = TaskPortForProcessID(error, force_update);
+ if (old_task != new_task) {
+ if (log)
+ log->Printf("exec: inferior task port changed "
+ "from 0x%4.4x to 0x%4.4x",
+ old_task, new_task);
}
+ }
+ } else {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() warning: "
+ "failed to read all_image_infos."
+ "infoArrayCount from 0x%8.8llx",
+ __FUNCTION__, info_array_count_addr);
}
+ } else if ((m_sent_interrupt_signo != 0) &&
+ (signo == m_sent_interrupt_signo)) {
+ // We just received the interrupt that we sent to ourselves.
+ received_interrupt = true;
+ }
}
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
- m_thread_list.ProcessDidStop(*this);
-
- // Let each thread know of any exceptions
- for (i = 0; i < m_exception_messages.size(); ++i)
- {
- // Let the thread list forward all exceptions on down to each thread.
- if (m_exception_messages[i].state.task_port == task)
- {
- // This exception is for our inferior.
- m_thread_list.NotifyException(m_exception_messages[i].state);
- }
+ if (m_did_exec) {
+ cpu_type_t process_cpu_type = GetCPUTypeForLocalProcess(m_pid);
+ if (m_cpu_type != process_cpu_type) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): arch changed from "
+ "0x%8.8x to 0x%8.8x",
+ __FUNCTION__, m_cpu_type, process_cpu_type);
+ m_cpu_type = process_cpu_type;
+ // TODO figure out if we need to do something here.
+ // DNBArchProtocol::SetArchitecture (process_cpu_type);
+ }
+ m_thread_list.Clear();
+
+ // TODO hook up breakpoints.
+ // m_breakpoints.DisableAll();
+ }
+ if (m_sent_interrupt_signo != 0) {
+ if (received_interrupt) {
if (log)
- {
- StreamString stream;
- m_exception_messages[i].Dump(stream);
- stream.Flush();
- log->PutCString(stream.GetString().c_str());
+ log->Printf("NativeProcessDarwin::%s(): process "
+ "successfully interrupted with signal %i",
+ __FUNCTION__, m_sent_interrupt_signo);
+
+ // Mark that we received the interrupt signal
+ m_sent_interrupt_signo = 0;
+ // Now check if we had a case where:
+ // 1 - We called NativeProcessDarwin::Interrupt() but we stopped
+ // for another reason.
+ // 2 - We called NativeProcessDarwin::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;
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): auto "
+ "resuming due to unhandled interrupt "
+ "signal %i",
+ __FUNCTION__, m_auto_resume_signo);
+ }
+ m_auto_resume_signo = 0;
}
+ } else {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): didn't get signal "
+ "%i after MachProcess::Interrupt()",
+ __FUNCTION__, m_sent_interrupt_signo);
+ }
}
-
- if (log)
- {
- StreamString stream;
- m_thread_list.Dump(stream);
- stream.Flush();
- log->PutCString(stream.GetString().c_str());
+ }
+
+ // Let all threads recover from stopping and do any clean up based
+ // on the previous thread state (if any).
+ m_thread_list.ProcessDidStop(*this);
+
+ // Let each thread know of any exceptions
+ for (i = 0; i < m_exception_messages.size(); ++i) {
+ // Let the thread list forward all exceptions on down to each thread.
+ if (m_exception_messages[i].state.task_port == task) {
+ // This exception is for our inferior.
+ m_thread_list.NotifyException(m_exception_messages[i].state);
}
- bool step_more = false;
- if (m_thread_list.ShouldStop(step_more) && (auto_resume == false))
- {
- // TODO - need to hook up event system here. !!!!
+ if (log) {
+ StreamString stream;
+ m_exception_messages[i].Dump(stream);
+ stream.Flush();
+ log->PutCString(stream.GetString().c_str());
+ }
+ }
+
+ if (log) {
+ StreamString stream;
+ m_thread_list.Dump(stream);
+ stream.Flush();
+ log->PutCString(stream.GetString().c_str());
+ }
+
+ bool step_more = false;
+ if (m_thread_list.ShouldStop(step_more) && (auto_resume == false)) {
+// TODO - need to hook up event system here. !!!!
#if 0
// Wait for the eEventProcessRunningStateChanged event to be reset
// before changing state to stopped to avoid race condition with
@@ -990,836 +870,707 @@ NativeProcessDarwin::ExceptionMessageBundleComplete()
m_events.WaitForEventsToReset(eEventProcessRunningStateChanged,
&timeout);
#endif
- SetState(eStateStopped);
- }
- else
- {
- // Resume without checking our current state.
- PrivateResume();
- }
+ SetState(eStateStopped);
+ } else {
+ // Resume without checking our current state.
+ PrivateResume();
+ }
- return m_task;
+ return m_task;
}
-void
-NativeProcessDarwin::StartSTDIOThread()
-{
- // TODO implement
+void NativeProcessDarwin::StartSTDIOThread() {
+ // TODO implement
}
-Error
-NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // Strategy: create a thread that sits on waitpid(), waiting for the
- // inferior process to die, reaping it in the process. Arrange for
- // the thread to have a pipe file descriptor that it can send a byte
- // over when the waitpid completes. Have the main loop have a read
- // object for the other side of the pipe, and have the callback for
- // the read do the process termination message sending.
-
- // Create a single-direction communication channel.
- const bool child_inherits = false;
- error = m_waitpid_pipe.CreateNew(child_inherits);
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failed to create waitpid "
- "communication pipe: %s", __FUNCTION__,
- error.AsCString());
- return error;
- }
-
- // Hook up the waitpid reader callback.
-
- // TODO make PipePOSIX derive from IOObject. This is goofy here.
- const bool transfer_ownership = false;
- auto io_sp = IOObjectSP(new File(m_waitpid_pipe.GetReadFileDescriptor(),
- transfer_ownership));
- m_waitpid_reader_handle =
- main_loop.RegisterReadObject(
- io_sp,
- [this](MainLoopBase &){ HandleWaitpidResult(); },
- error);
-
- // Create the thread.
- auto pthread_err = ::pthread_create(&m_waitpid_thread, nullptr,
- WaitpidThread, this);
- error.SetError(pthread_err, eErrorTypePOSIX);
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failed to create waitpid "
- "handling thread: %u (%s)", __FUNCTION__,
- error.GetError(), error.AsCString());
- return error;
- }
-
+Error NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Strategy: create a thread that sits on waitpid(), waiting for the
+ // inferior process to die, reaping it in the process. Arrange for
+ // the thread to have a pipe file descriptor that it can send a byte
+ // over when the waitpid completes. Have the main loop have a read
+ // object for the other side of the pipe, and have the callback for
+ // the read do the process termination message sending.
+
+ // Create a single-direction communication channel.
+ const bool child_inherits = false;
+ error = m_waitpid_pipe.CreateNew(child_inherits);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): failed to create waitpid "
+ "communication pipe: %s",
+ __FUNCTION__, error.AsCString());
return error;
+ }
+
+ // Hook up the waitpid reader callback.
+
+ // TODO make PipePOSIX derive from IOObject. This is goofy here.
+ const bool transfer_ownership = false;
+ auto io_sp = IOObjectSP(
+ new File(m_waitpid_pipe.GetReadFileDescriptor(), transfer_ownership));
+ m_waitpid_reader_handle = main_loop.RegisterReadObject(
+ io_sp, [this](MainLoopBase &) { HandleWaitpidResult(); }, error);
+
+ // Create the thread.
+ auto pthread_err =
+ ::pthread_create(&m_waitpid_thread, nullptr, WaitpidThread, this);
+ error.SetError(pthread_err, eErrorTypePOSIX);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): failed to create waitpid "
+ "handling thread: %u (%s)",
+ __FUNCTION__, error.GetError(), error.AsCString());
+ return error;
+ }
+
+ return error;
}
-void*
-NativeProcessDarwin::WaitpidThread(void *arg)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!arg)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): cannot run waitpid "
- "thread, mandatory process arg was null", __FUNCTION__);
- return nullptr;
- }
+void *NativeProcessDarwin::WaitpidThread(void *arg) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (!arg) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): cannot run waitpid "
+ "thread, mandatory process arg was null",
+ __FUNCTION__);
+ return nullptr;
+ }
- return reinterpret_cast<NativeProcessDarwin*>(arg)->DoWaitpidThread();
+ return reinterpret_cast<NativeProcessDarwin *>(arg)->DoWaitpidThread();
}
-void
-NativeProcessDarwin::MaybeRaiseThreadPriority()
-{
-#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 NativeProcessDarwin::MaybeRaiseThreadPriority() {
+#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
}
-void*
-NativeProcessDarwin::DoWaitpidThread()
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- if (m_pid == LLDB_INVALID_PROCESS_ID)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): inferior process ID is "
- "not set, cannot waitpid on it", __FUNCTION__);
- return nullptr;
- }
-
- // Name the thread.
- pthread_setname_np("waitpid thread");
-
- // Ensure we don't get CPU starved.
- MaybeRaiseThreadPriority();
-
- Error error;
- int status = -1;
+void *NativeProcessDarwin::DoWaitpidThread() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- while (1)
- {
- // Do a waitpid.
- ::pid_t child_pid = ::waitpid(m_pid, &status, 0);
- if (child_pid < 0)
- error.SetErrorToErrno();
- if (error.Fail())
- {
- if (error.GetError() == EINTR)
- {
- // This is okay, we can keep going.
- if (log)
- log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %"
- PRIu64 ", &status, 0) interrupted, continuing",
- __FUNCTION__, m_pid);
- continue;
- }
-
- // This error is not okay, abort.
- if (log)
- log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
- ", &status, 0) aborting due to error: %u (%s)",
- __FUNCTION__, m_pid, error.GetError(),
- error.AsCString());
- break;
- }
-
- // Log the successful result.
- if (log)
- log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
- ", &status, 0) => %i, status = %i", __FUNCTION__,
- m_pid, child_pid, status);
-
- // Handle the result.
- if (WIFSTOPPED(status))
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
- ") received a stop, continuing waitpid() loop",
- __FUNCTION__, m_pid);
- continue;
- }
- else // if (WIFEXITED(status) || WIFSIGNALED(status))
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(pid = %" PRIu64 "): "
- "waitpid thread is setting exit status for pid = "
- "%i to %i", __FUNCTION__, m_pid,
- child_pid, status);
-
- error = SendInferiorExitStatusToMainLoop(child_pid, status);
- return nullptr;
- }
- }
-
- // We should never exit as long as our child process is alive. If we
- // get here, something completely unexpected went wrong and we should exit.
+ if (m_pid == LLDB_INVALID_PROCESS_ID) {
if (log)
- log->Printf("NativeProcessDarwin::%s(): internal error: waitpid thread "
- "exited out of its main loop in an unexpected way. pid = %"
- PRIu64 ". Sending exit status of -1.", __FUNCTION__, m_pid);
-
- error = SendInferiorExitStatusToMainLoop((::pid_t)m_pid, -1);
+ log->Printf("NativeProcessDarwin::%s(): inferior process ID is "
+ "not set, cannot waitpid on it",
+ __FUNCTION__);
return nullptr;
-}
+ }
-Error
-NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid, int status)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ // Name the thread.
+ pthread_setname_np("waitpid thread");
- size_t bytes_written = 0;
+ // Ensure we don't get CPU starved.
+ MaybeRaiseThreadPriority();
- // Send the pid.
- error = m_waitpid_pipe.Write(&pid, sizeof(pid), bytes_written);
- if (error.Fail() || (bytes_written < sizeof(pid)))
- {
+ Error error;
+ int status = -1;
+
+ while (1) {
+ // Do a waitpid.
+ ::pid_t child_pid = ::waitpid(m_pid, &status, 0);
+ if (child_pid < 0)
+ error.SetErrorToErrno();
+ if (error.Fail()) {
+ if (error.GetError() == EINTR) {
+ // This is okay, we can keep going.
if (log)
- log->Printf("NativeProcessDarwin::%s() - failed to write "
- "waitpid exiting pid to the pipe. Client will not "
- "hear about inferior exit status!",
- __FUNCTION__);
- return error;
+ log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
+ ", &status, 0) interrupted, continuing",
+ __FUNCTION__, m_pid);
+ continue;
+ }
+
+ // This error is not okay, abort.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
+ ", &status, 0) aborting due to error: %u (%s)",
+ __FUNCTION__, m_pid, error.GetError(), error.AsCString());
+ break;
}
- // Send the status.
- bytes_written = 0;
- error = m_waitpid_pipe.Write(&status, sizeof(status), bytes_written);
- if (error.Fail() || (bytes_written < sizeof(status)))
+ // Log the successful result.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
+ ", &status, 0) => %i, status = %i",
+ __FUNCTION__, m_pid, child_pid, status);
+
+ // Handle the result.
+ if (WIFSTOPPED(status)) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
+ ") received a stop, continuing waitpid() loop",
+ __FUNCTION__, m_pid);
+ continue;
+ } else // if (WIFEXITED(status) || WIFSIGNALED(status))
{
- if (log)
- log->Printf("NativeProcessDarwin::%s() - failed to write "
- "waitpid exit result to the pipe. Client will not "
- "hear about inferior exit status!",
- __FUNCTION__);
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(pid = %" PRIu64 "): "
+ "waitpid thread is setting exit status for pid = "
+ "%i to %i",
+ __FUNCTION__, m_pid, child_pid, status);
+
+ error = SendInferiorExitStatusToMainLoop(child_pid, status);
+ return nullptr;
}
- return error;
+ }
+
+ // We should never exit as long as our child process is alive. If we
+ // get here, something completely unexpected went wrong and we should exit.
+ if (log)
+ log->Printf(
+ "NativeProcessDarwin::%s(): internal error: waitpid thread "
+ "exited out of its main loop in an unexpected way. pid = %" PRIu64
+ ". Sending exit status of -1.",
+ __FUNCTION__, m_pid);
+
+ error = SendInferiorExitStatusToMainLoop((::pid_t)m_pid, -1);
+ return nullptr;
}
-Error
-NativeProcessDarwin::HandleWaitpidResult()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // Read the pid.
- const bool notify_status = true;
+Error NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid,
+ int status) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- ::pid_t pid = -1;
- size_t bytes_read = 0;
- error = m_waitpid_pipe.Read(&pid, sizeof(pid), bytes_read);
- if (error.Fail() || (bytes_read < sizeof(pid)))
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s() - failed to read "
- "waitpid exiting pid from the pipe. Will notify "
- "as if parent process died with exit status -1.",
- __FUNCTION__);
- SetExitStatus(eExitTypeInvalid, -1, "failed to receive waitpid result",
- notify_status);
- return error;
- }
+ size_t bytes_written = 0;
- // Read the status.
- int status = -1;
- error = m_waitpid_pipe.Read(&status, sizeof(status), bytes_read);
- if (error.Fail() || (bytes_read < sizeof(status)))
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s() - failed to read "
- "waitpid exit status from the pipe. Will notify "
- "as if parent process died with exit status -1.",
- __FUNCTION__);
- SetExitStatus(eExitTypeInvalid, -1, "failed to receive waitpid result",
- notify_status);
- return error;
- }
+ // Send the pid.
+ error = m_waitpid_pipe.Write(&pid, sizeof(pid), bytes_written);
+ if (error.Fail() || (bytes_written < sizeof(pid))) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() - failed to write "
+ "waitpid exiting pid to the pipe. Client will not "
+ "hear about inferior exit status!",
+ __FUNCTION__);
+ return error;
+ }
- // Notify the monitor that our state has changed.
+ // Send the status.
+ bytes_written = 0;
+ error = m_waitpid_pipe.Write(&status, sizeof(status), bytes_written);
+ if (error.Fail() || (bytes_written < sizeof(status))) {
if (log)
- log->Printf("NativeProcessDarwin::%s(): main loop received waitpid "
- "exit status info: pid=%i (%s), status=%i",
- __FUNCTION__, pid,
- (pid == m_pid) ? "the inferior" : "not the inferior",
- status);
+ log->Printf("NativeProcessDarwin::%s() - failed to write "
+ "waitpid exit result to the pipe. Client will not "
+ "hear about inferior exit status!",
+ __FUNCTION__);
+ }
+ return error;
+}
- ExitType exit_type = eExitTypeInvalid;
- int exit_status = -1;
+Error NativeProcessDarwin::HandleWaitpidResult() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (WIFEXITED(status))
- {
- exit_type = eExitTypeExit;
- exit_status = WEXITSTATUS(status);
- }
- else if (WIFSIGNALED(status))
- {
- exit_type = eExitTypeSignal;
- exit_status = WTERMSIG(status);
- }
+ // Read the pid.
+ const bool notify_status = true;
+
+ ::pid_t pid = -1;
+ size_t bytes_read = 0;
+ error = m_waitpid_pipe.Read(&pid, sizeof(pid), bytes_read);
+ if (error.Fail() || (bytes_read < sizeof(pid))) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() - failed to read "
+ "waitpid exiting pid from the pipe. Will notify "
+ "as if parent process died with exit status -1.",
+ __FUNCTION__);
+ SetExitStatus(eExitTypeInvalid, -1, "failed to receive waitpid result",
+ notify_status);
+ return error;
+ }
- SetExitStatus(exit_type, exit_status, nullptr, notify_status);
+ // Read the status.
+ int status = -1;
+ error = m_waitpid_pipe.Read(&status, sizeof(status), bytes_read);
+ if (error.Fail() || (bytes_read < sizeof(status))) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() - failed to read "
+ "waitpid exit status from the pipe. Will notify "
+ "as if parent process died with exit status -1.",
+ __FUNCTION__);
+ SetExitStatus(eExitTypeInvalid, -1, "failed to receive waitpid result",
+ notify_status);
return error;
+ }
+
+ // Notify the monitor that our state has changed.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): main loop received waitpid "
+ "exit status info: pid=%i (%s), status=%i",
+ __FUNCTION__, pid,
+ (pid == m_pid) ? "the inferior" : "not the inferior", status);
+
+ ExitType exit_type = eExitTypeInvalid;
+ int exit_status = -1;
+
+ if (WIFEXITED(status)) {
+ exit_type = eExitTypeExit;
+ exit_status = WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ exit_type = eExitTypeSignal;
+ exit_status = WTERMSIG(status);
+ }
+
+ SetExitStatus(exit_type, exit_status, nullptr, notify_status);
+ return error;
}
-task_t
-NativeProcessDarwin::TaskPortForProcessID(Error &error, bool force) const
-{
- if ((m_task == TASK_NULL) || force)
- {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (m_pid == LLDB_INVALID_PROCESS_ID)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): cannot get task due "
- "to invalid pid", __FUNCTION__);
- return TASK_NULL;
- }
+task_t NativeProcessDarwin::TaskPortForProcessID(Error &error,
+ bool force) const {
+ if ((m_task == TASK_NULL) || force) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (m_pid == LLDB_INVALID_PROCESS_ID) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): cannot get task due "
+ "to invalid pid",
+ __FUNCTION__);
+ return TASK_NULL;
+ }
- const uint32_t num_retries = 10;
- const uint32_t usec_interval = 10000;
-
- mach_port_t task_self = mach_task_self();
- task_t task = TASK_NULL;
-
- for (uint32_t i = 0; i < num_retries; i++)
- {
- kern_return_t err = ::task_for_pid(task_self, m_pid, &task);
- if (err == 0)
- {
- // Succeeded. Save and return it.
- error.Clear();
- m_task = task;
- log->Printf("NativeProcessDarwin::%s(): ::task_for_pid("
- "stub_port = 0x%4.4x, pid = %llu, &task) "
- "succeeded: inferior task port = 0x%4.4x",
- __FUNCTION__, task_self, m_pid, m_task);
- return m_task;
- }
- else
- {
- // Failed to get the task for the inferior process.
- error.SetError(err, eErrorTypeMachKernel);
- if (log)
- {
- log->Printf("NativeProcessDarwin::%s(): ::task_for_pid("
- "stub_port = 0x%4.4x, pid = %llu, &task) "
- "failed, err = 0x%8.8x (%s)",
- __FUNCTION__, task_self,
- m_pid,
- err,
- error.AsCString());
- }
- }
+ const uint32_t num_retries = 10;
+ const uint32_t usec_interval = 10000;
- // Sleep a bit and try again
- ::usleep (usec_interval);
+ mach_port_t task_self = mach_task_self();
+ task_t task = TASK_NULL;
+
+ for (uint32_t i = 0; i < num_retries; i++) {
+ kern_return_t err = ::task_for_pid(task_self, m_pid, &task);
+ if (err == 0) {
+ // Succeeded. Save and return it.
+ error.Clear();
+ m_task = task;
+ log->Printf("NativeProcessDarwin::%s(): ::task_for_pid("
+ "stub_port = 0x%4.4x, pid = %llu, &task) "
+ "succeeded: inferior task port = 0x%4.4x",
+ __FUNCTION__, task_self, m_pid, m_task);
+ return m_task;
+ } else {
+ // Failed to get the task for the inferior process.
+ error.SetError(err, eErrorTypeMachKernel);
+ if (log) {
+ log->Printf("NativeProcessDarwin::%s(): ::task_for_pid("
+ "stub_port = 0x%4.4x, pid = %llu, &task) "
+ "failed, err = 0x%8.8x (%s)",
+ __FUNCTION__, task_self, m_pid, err, error.AsCString());
}
+ }
- // We failed to get the task for the inferior process.
- // Ensure that it is cleared out.
- m_task = TASK_NULL;
+ // Sleep a bit and try again
+ ::usleep(usec_interval);
}
- return m_task;
-}
-void
-NativeProcessDarwin::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
- Error &error)
-{
- error.SetErrorString("TODO: implement");
+ // We failed to get the task for the inferior process.
+ // Ensure that it is cleared out.
+ m_task = TASK_NULL;
+ }
+ return m_task;
}
-Error
-NativeProcessDarwin::PrivateResume()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
- m_auto_resume_signo = m_sent_interrupt_signo;
-
- if (log)
- {
- if (m_auto_resume_signo)
- log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming (with "
- "unhandled interrupt signal %i)...", __FUNCTION__,
- m_task, m_auto_resume_signo);
- else
- log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming...",
- __FUNCTION__, m_task);
- }
+void NativeProcessDarwin::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
+ Error &error) {
+ error.SetErrorString("TODO: implement");
+}
- error = ReplyToAllExceptions();
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): aborting, failed to "
- "reply to exceptions: %s", __FUNCTION__,
- error.AsCString());
- return error;
- }
- // bool stepOverBreakInstruction = step;
+Error NativeProcessDarwin::PrivateResume() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- // 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);
+ std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
+ m_auto_resume_signo = m_sent_interrupt_signo;
- // Set our state accordingly
- if (m_thread_actions.NumActionsWithState(eStateStepping))
- SetState(eStateStepping);
+ if (log) {
+ if (m_auto_resume_signo)
+ log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming (with "
+ "unhandled interrupt signal %i)...",
+ __FUNCTION__, m_task, m_auto_resume_signo);
else
- SetState(eStateRunning);
+ log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming...",
+ __FUNCTION__, m_task);
+ }
- // Now resume our task.
- error = ResumeTask();
+ error = ReplyToAllExceptions();
+ if (error.Fail()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): aborting, failed to "
+ "reply to exceptions: %s",
+ __FUNCTION__, error.AsCString());
return error;
+ }
+ // 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.
+ error = ResumeTask();
+ return error;
}
-Error
-NativeProcessDarwin::ReplyToAllExceptions()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
+Error NativeProcessDarwin::ReplyToAllExceptions() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
- TaskPortForProcessID(error);
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): no task port, aborting",
- __FUNCTION__);
- return error;
- }
+ TaskPortForProcessID(error);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): no task port, aborting",
+ __FUNCTION__);
+ return error;
+ }
- std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
- if (m_exception_messages.empty())
- {
- // We're done.
- return error;
+ std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
+ if (m_exception_messages.empty()) {
+ // We're done.
+ return error;
+ }
+
+ size_t index = 0;
+ for (auto &message : m_exception_messages) {
+ if (log) {
+ log->Printf("NativeProcessDarwin::%s(): replying to exception "
+ "%zu...",
+ __FUNCTION__, index++);
}
- size_t index = 0;
- for (auto &message : m_exception_messages)
- {
- if (log)
- {
- log->Printf("NativeProcessDarwin::%s(): replying to exception "
- "%zu...", __FUNCTION__, index++);
- }
-
- int thread_reply_signal = 0;
+ int thread_reply_signal = 0;
- const tid_t tid =
- m_thread_list.GetThreadIDByMachPortNumber(message.state
- .thread_port);
- const ResumeAction *action = nullptr;
- if (tid != LLDB_INVALID_THREAD_ID)
- action = m_thread_actions.GetActionForThread (tid, false);
+ const tid_t tid =
+ m_thread_list.GetThreadIDByMachPortNumber(message.state.thread_port);
+ const ResumeAction *action = nullptr;
+ if (tid != LLDB_INVALID_THREAD_ID)
+ action = m_thread_actions.GetActionForThread(tid, false);
- if (action)
- {
- thread_reply_signal = action->signal;
- if (thread_reply_signal)
- m_thread_actions.SetSignalHandledForThread(tid);
- }
+ if (action) {
+ thread_reply_signal = action->signal;
+ if (thread_reply_signal)
+ m_thread_actions.SetSignalHandledForThread(tid);
+ }
- error = message.Reply(m_pid, m_task, thread_reply_signal);
- if (error.Fail() && log)
- {
- // We log any error here, but we don't stop the exception
- // response handling.
- log->Printf("NativeProcessDarwin::%s(): failed to reply to "
- "exception: %s", __FUNCTION__, error.AsCString());
- error.Clear();
- }
+ error = message.Reply(m_pid, m_task, thread_reply_signal);
+ if (error.Fail() && log) {
+ // We log any error here, but we don't stop the exception
+ // response handling.
+ log->Printf("NativeProcessDarwin::%s(): failed to reply to "
+ "exception: %s",
+ __FUNCTION__, error.AsCString());
+ error.Clear();
}
+ }
- // Erase all exception message as we should have used and replied
- // to them all already.
- m_exception_messages.clear();
- return error;
+ // Erase all exception message as we should have used and replied
+ // to them all already.
+ m_exception_messages.clear();
+ return error;
}
-Error
-NativeProcessDarwin::ResumeTask()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- TaskPortForProcessID(error);
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failed to get task port "
- "for process when attempting to resume: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
- if (m_task == TASK_NULL)
- {
- error.SetErrorString("task port retrieval succeeded but task port is "
- "null when attempting to resume the task");
- return error;
- }
+Error NativeProcessDarwin::ResumeTask() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ TaskPortForProcessID(error);
+ if (error.Fail()) {
if (log)
- log->Printf("NativeProcessDarwin::%s(): requesting resume of task "
- "0x%4.4x", __FUNCTION__, m_task);
-
- // Get the BasicInfo struct to verify that we're suspended before we try
- // to resume the task.
- struct task_basic_info task_info;
- error = GetTaskBasicInfo(m_task, &task_info);
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failed to get task "
- "BasicInfo when attempting to resume: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
+ log->Printf("NativeProcessDarwin::%s(): failed to get task port "
+ "for process when attempting to resume: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ }
+ if (m_task == TASK_NULL) {
+ error.SetErrorString("task port retrieval succeeded but task port is "
+ "null when attempting to resume the task");
+ return error;
+ }
+
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): requesting resume of task "
+ "0x%4.4x",
+ __FUNCTION__, m_task);
+
+ // Get the BasicInfo struct to verify that we're suspended before we try
+ // to resume the task.
+ struct task_basic_info task_info;
+ error = GetTaskBasicInfo(m_task, &task_info);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): failed to get task "
+ "BasicInfo when attempting to resume: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ }
- // task_resume isn't counted like task_suspend calls are, so if the
- // task is not suspended, don't try and resume it since it is already
- // running
- if (task_info.suspend_count > 0)
- {
- auto mach_err = ::task_resume(m_task);
- error.SetError(mach_err, eErrorTypeMachKernel);
- if (log)
- {
- if (error.Success())
- log->Printf("::task_resume(target_task = 0x%4.4x): success",
- m_task);
- else
- log->Printf("::task_resume(target_task = 0x%4.4x) error: %s",
- m_task, error.AsCString());
- }
- }
- else
- {
- if (log)
- log->Printf("::task_resume(target_task = 0x%4.4x): ignored, "
- "already running", m_task);
+ // task_resume isn't counted like task_suspend calls are, so if the
+ // task is not suspended, don't try and resume it since it is already
+ // running
+ if (task_info.suspend_count > 0) {
+ auto mach_err = ::task_resume(m_task);
+ error.SetError(mach_err, eErrorTypeMachKernel);
+ if (log) {
+ if (error.Success())
+ log->Printf("::task_resume(target_task = 0x%4.4x): success", m_task);
+ else
+ log->Printf("::task_resume(target_task = 0x%4.4x) error: %s", m_task,
+ error.AsCString());
}
+ } else {
+ if (log)
+ log->Printf("::task_resume(target_task = 0x%4.4x): ignored, "
+ "already running",
+ m_task);
+ }
- return error;
+ return error;
}
-bool
-NativeProcessDarwin::IsTaskValid() const
-{
- if (m_task == TASK_NULL)
- return false;
+bool NativeProcessDarwin::IsTaskValid() const {
+ if (m_task == TASK_NULL)
+ return false;
- struct task_basic_info task_info;
- return GetTaskBasicInfo(m_task, &task_info).Success();
+ struct task_basic_info task_info;
+ return GetTaskBasicInfo(m_task, &task_info).Success();
}
-bool
-NativeProcessDarwin::IsTaskValid(task_t task) const
-{
- if (task == TASK_NULL)
- return false;
+bool NativeProcessDarwin::IsTaskValid(task_t task) const {
+ if (task == TASK_NULL)
+ return false;
- struct task_basic_info task_info;
- return GetTaskBasicInfo(task, &task_info).Success();
+ struct task_basic_info task_info;
+ return GetTaskBasicInfo(task, &task_info).Success();
}
-mach_port_t
-NativeProcessDarwin::GetExceptionPort() const
-{
- return m_exception_port;
+mach_port_t NativeProcessDarwin::GetExceptionPort() const {
+ return m_exception_port;
}
-bool
-NativeProcessDarwin::IsExceptionPortValid () const
-{
- return MACH_PORT_VALID(m_exception_port);
+bool NativeProcessDarwin::IsExceptionPortValid() const {
+ return MACH_PORT_VALID(m_exception_port);
}
-Error
-NativeProcessDarwin::GetTaskBasicInfo(task_t task,
- struct task_basic_info *info) const
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // Validate args.
- if (info == NULL)
- {
- error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): mandatory "
- "info arg is null", __FUNCTION__);
- return error;
- }
-
- // Grab the task if we don't already have it.
- if (task == TASK_NULL)
- {
- error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): given task "
- "is invalid", __FUNCTION__);
- }
-
- mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
- auto err = ::task_info(m_task, TASK_BASIC_INFO, (task_info_t)info, &count);
- error.SetError(err, eErrorTypeMachKernel);
- if (error.Fail())
- {
- if (log)
- log->Printf("::task_info(target_task = 0x%4.4x, "
- "flavor = TASK_BASIC_INFO, task_info_out => %p, "
- "task_info_outCnt => %u) failed: %u (%s)", m_task, info,
- count, error.GetError(), error.AsCString());
- return error;
- }
+Error NativeProcessDarwin::GetTaskBasicInfo(
+ task_t task, struct task_basic_info *info) const {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- Log *verbose_log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
- if (verbose_log)
- {
- float user = (float)info->user_time.seconds +
- (float)info->user_time.microseconds / 1000000.0f;
- float system = (float)info->user_time.seconds +
- (float)info->user_time.microseconds / 1000000.0f;
- verbose_log->Printf("task_basic_info = { suspend_count = %i, "
- "virtual_size = 0x%8.8llx, resident_size = "
- "0x%8.8llx, user_time = %f, system_time = %f }",
- info->suspend_count,
- (uint64_t)info->virtual_size,
- (uint64_t)info->resident_size,
- user, system);
- }
+ // Validate args.
+ if (info == NULL) {
+ error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): mandatory "
+ "info arg is null",
+ __FUNCTION__);
return error;
+ }
+
+ // Grab the task if we don't already have it.
+ if (task == TASK_NULL) {
+ error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): given task "
+ "is invalid",
+ __FUNCTION__);
+ }
+
+ mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
+ auto err = ::task_info(m_task, TASK_BASIC_INFO, (task_info_t)info, &count);
+ error.SetError(err, eErrorTypeMachKernel);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("::task_info(target_task = 0x%4.4x, "
+ "flavor = TASK_BASIC_INFO, task_info_out => %p, "
+ "task_info_outCnt => %u) failed: %u (%s)",
+ m_task, info, count, error.GetError(), error.AsCString());
+ return error;
+ }
+
+ Log *verbose_log(
+ GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+ if (verbose_log) {
+ float user = (float)info->user_time.seconds +
+ (float)info->user_time.microseconds / 1000000.0f;
+ float system = (float)info->user_time.seconds +
+ (float)info->user_time.microseconds / 1000000.0f;
+ verbose_log->Printf("task_basic_info = { suspend_count = %i, "
+ "virtual_size = 0x%8.8llx, resident_size = "
+ "0x%8.8llx, user_time = %f, system_time = %f }",
+ info->suspend_count, (uint64_t)info->virtual_size,
+ (uint64_t)info->resident_size, user, system);
+ }
+ return error;
}
-Error
-NativeProcessDarwin::SuspendTask()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- if (m_task == TASK_NULL)
- {
- error.SetErrorString("task port is null, cannot suspend task");
- if (log)
- log->Printf("NativeProcessDarwin::%s() failed: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
-
- auto mach_err = ::task_suspend(m_task);
- error.SetError(mach_err, eErrorTypeMachKernel);
- if (error.Fail() && log)
- log->Printf("::task_suspend(target_task = 0x%4.4x)", m_task);
+Error NativeProcessDarwin::SuspendTask() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (m_task == TASK_NULL) {
+ error.SetErrorString("task port is null, cannot suspend task");
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() failed: %s", __FUNCTION__,
+ error.AsCString());
return error;
-}
+ }
-Error
-NativeProcessDarwin::Resume(const ResumeActionList &resume_actions)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ auto mach_err = ::task_suspend(m_task);
+ error.SetError(mach_err, eErrorTypeMachKernel);
+ if (error.Fail() && log)
+ log->Printf("::task_suspend(target_task = 0x%4.4x)", m_task);
- if (log)
- log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__);
+ return error;
+}
- if (CanResume())
- {
- m_thread_actions = resume_actions;
- error = PrivateResume();
- return error;
- }
+Error NativeProcessDarwin::Resume(const ResumeActionList &resume_actions) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- auto state = GetState();
- if (state == eStateRunning)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): task 0x%x is already "
- "running, ignoring...", __FUNCTION__,
- TaskPortForProcessID(error));
- return error;
- }
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__);
- // We can't resume from this state.
- error.SetErrorStringWithFormat("task 0x%x has state %s, can't resume",
- TaskPortForProcessID(error),
- StateAsCString(state));
+ if (CanResume()) {
+ m_thread_actions = resume_actions;
+ error = PrivateResume();
return error;
-}
+ }
-Error
-NativeProcessDarwin::Halt()
-{
- Error error;
- error.SetErrorString("TODO: implement");
+ auto state = GetState();
+ if (state == eStateRunning) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): task 0x%x is already "
+ "running, ignoring...",
+ __FUNCTION__, TaskPortForProcessID(error));
return error;
-}
+ }
-Error
-NativeProcessDarwin::Detach()
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+ // We can't resume from this state.
+ error.SetErrorStringWithFormat("task 0x%x has state %s, can't resume",
+ TaskPortForProcessID(error),
+ StateAsCString(state));
+ return error;
}
-Error
-NativeProcessDarwin::Signal(int signo)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::Halt() {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::Interrupt()
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::Detach() {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::Kill()
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::Signal(int signo) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::GetMemoryRegionInfo(lldb::addr_t load_addr,
- MemoryRegionInfo &range_info)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::Interrupt() {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
- size_t &bytes_read)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::Kill() {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
- size_t size, size_t &bytes_read)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &range_info) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::WriteMemory(lldb::addr_t addr, const void *buf,
- size_t size, size_t &bytes_written)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ size_t &bytes_read) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::AllocateMemory(size_t size, uint32_t permissions,
- lldb::addr_t &addr)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
+ size_t size,
+ size_t &bytes_read) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::DeallocateMemory(lldb::addr_t addr)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::WriteMemory(lldb::addr_t addr, const void *buf,
+ size_t size, size_t &bytes_written) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-lldb::addr_t
-NativeProcessDarwin::GetSharedLibraryInfoAddress()
-{
- return LLDB_INVALID_ADDRESS;
+Error NativeProcessDarwin::AllocateMemory(size_t size, uint32_t permissions,
+ lldb::addr_t &addr) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-size_t
-NativeProcessDarwin::UpdateThreads()
-{
- return 0;
+Error NativeProcessDarwin::DeallocateMemory(lldb::addr_t addr) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-bool
-NativeProcessDarwin::GetArchitecture(ArchSpec &arch) const
-{
- return false;
+lldb::addr_t NativeProcessDarwin::GetSharedLibraryInfoAddress() {
+ return LLDB_INVALID_ADDRESS;
}
-Error
-NativeProcessDarwin::SetBreakpoint(lldb::addr_t addr, uint32_t size,
- bool hardware)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+size_t NativeProcessDarwin::UpdateThreads() { return 0; }
+
+bool NativeProcessDarwin::GetArchitecture(ArchSpec &arch) const {
+ return false;
}
-void
-NativeProcessDarwin::DoStopIDBumped(uint32_t newBumpId)
-{
+Error NativeProcessDarwin::SetBreakpoint(lldb::addr_t addr, uint32_t size,
+ bool hardware) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::GetLoadedModuleFileSpec(const char* module_path,
- FileSpec& file_spec)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+void NativeProcessDarwin::DoStopIDBumped(uint32_t newBumpId) {}
+
+Error NativeProcessDarwin::GetLoadedModuleFileSpec(const char *module_path,
+ FileSpec &file_spec) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::GetFileLoadAddress(const llvm::StringRef& file_name,
- lldb::addr_t& load_addr)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::GetFileLoadAddress(const llvm::StringRef &file_name,
+ lldb::addr_t &load_addr) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
// -----------------------------------------------------------------
// NativeProcessProtocol protected interface
// -----------------------------------------------------------------
-Error
-NativeProcessDarwin::GetSoftwareBreakpointTrapOpcode(size_t
- trap_opcode_size_hint,
- size_t &actual_opcode_size,
- const uint8_t
- *&trap_opcode_bytes)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::GetSoftwareBreakpointTrapOpcode(
+ size_t trap_opcode_size_hint, size_t &actual_opcode_size,
+ const uint8_t *&trap_opcode_bytes) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
diff --git a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h b/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h
index 13077452245..69c1b8d9e4c 100644
--- a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h
+++ b/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h
@@ -23,217 +23,178 @@
// Other libraries and framework includes
#include "lldb/Core/ArchSpec.h"
-#include "lldb/lldb-types.h"
-#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/Debug.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/Pipe.h"
+#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/lldb-types.h"
-#include "NativeThreadListDarwin.h"
#include "LaunchFlavor.h"
#include "MachException.h"
#include "NativeThreadDarwin.h"
+#include "NativeThreadListDarwin.h"
namespace lldb_private {
- class Error;
- class Scalar;
+class Error;
+class Scalar;
+
+namespace process_darwin {
+
+/// @class NativeProcessDarwin
+/// @brief Manages communication with the inferior (debugee) process.
+///
+/// Upon construction, this class prepares and launches an inferior
+/// process for debugging.
+///
+/// Changes in the inferior process state are broadcasted.
+class NativeProcessDarwin : public NativeProcessProtocol {
+ friend Error NativeProcessProtocol::Launch(
+ ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
+ MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
+
+ friend Error NativeProcessProtocol::Attach(
+ lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
+ MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
+
+public:
+ ~NativeProcessDarwin() override;
+
+ // -----------------------------------------------------------------
+ // NativeProcessProtocol Interface
+ // -----------------------------------------------------------------
+ Error Resume(const ResumeActionList &resume_actions) override;
+
+ Error Halt() override;
+
+ Error Detach() override;
+
+ Error Signal(int signo) override;
+
+ Error Interrupt() override;
+
+ Error Kill() override;
+
+ Error GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &range_info) override;
+
+ Error ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ size_t &bytes_read) override;
+
+ Error ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size,
+ size_t &bytes_read) override;
+
+ Error WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
+ size_t &bytes_written) override;
+
+ Error AllocateMemory(size_t size, uint32_t permissions,
+ lldb::addr_t &addr) override;
+
+ Error DeallocateMemory(lldb::addr_t addr) override;
+
+ lldb::addr_t GetSharedLibraryInfoAddress() override;
- namespace process_darwin {
+ size_t UpdateThreads() override;
- /// @class NativeProcessDarwin
- /// @brief Manages communication with the inferior (debugee) process.
- ///
- /// Upon construction, this class prepares and launches an inferior
- /// process for debugging.
- ///
- /// Changes in the inferior process state are broadcasted.
- class NativeProcessDarwin: public NativeProcessProtocol
- {
- friend Error
- NativeProcessProtocol::Launch(ProcessLaunchInfo &launch_info,
- NativeDelegate &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &process_sp);
-
- friend Error
- NativeProcessProtocol::Attach(lldb::pid_t pid,
- NativeProcessProtocol::NativeDelegate
- &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &process_sp);
-
- public:
-
- ~NativeProcessDarwin() override;
-
- // -----------------------------------------------------------------
- // NativeProcessProtocol Interface
- // -----------------------------------------------------------------
- Error
- Resume(const ResumeActionList &resume_actions) override;
-
- Error
- Halt() override;
-
- Error
- Detach() override;
-
- Error
- Signal(int signo) override;
-
- Error
- Interrupt() override;
-
- Error
- Kill() override;
-
- Error
- GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo
- &range_info) override;
-
- Error
- ReadMemory(lldb::addr_t addr, void *buf, size_t size,
- size_t &bytes_read) override;
-
- Error
- ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size,
- size_t &bytes_read) override;
-
- Error
- WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
- size_t &bytes_written) override;
-
- Error
- AllocateMemory(size_t size, uint32_t permissions,
- lldb::addr_t &addr) override;
-
- Error
- DeallocateMemory(lldb::addr_t addr) override;
-
- lldb::addr_t
- GetSharedLibraryInfoAddress() override;
-
- size_t
- UpdateThreads() override;
-
- bool
- GetArchitecture(ArchSpec &arch) const override;
-
- Error
- SetBreakpoint(lldb::addr_t addr, uint32_t size,
- bool hardware) override;
-
- void
- DoStopIDBumped(uint32_t newBumpId) override;
-
- Error
- GetLoadedModuleFileSpec(const char* module_path,
- FileSpec& file_spec) override;
-
- Error
- GetFileLoadAddress(const llvm::StringRef& file_name,
- lldb::addr_t& load_addr) override;
-
- NativeThreadDarwinSP
- GetThreadByID(lldb::tid_t id);
-
- task_t
- GetTask() const
- {
- return m_task;
- }
-
- // -----------------------------------------------------------------
- // Interface used by NativeRegisterContext-derived classes.
- // -----------------------------------------------------------------
- static Error
- PtraceWrapper(int req,
- lldb::pid_t pid,
- void *addr = nullptr,
- void *data = nullptr,
- size_t data_size = 0,
- long *result = nullptr);
+ bool GetArchitecture(ArchSpec &arch) const override;
- bool
- SupportHardwareSingleStepping() const;
+ Error SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override;
- protected:
- // -----------------------------------------------------------------
- // NativeProcessProtocol protected interface
- // -----------------------------------------------------------------
- Error
- GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint,
- size_t &actual_opcode_size,
- const uint8_t *&trap_opcode_bytes)
- override;
+ void DoStopIDBumped(uint32_t newBumpId) override;
- private:
+ Error GetLoadedModuleFileSpec(const char *module_path,
+ FileSpec &file_spec) override;
- // -----------------------------------------------------------------
- /// Mach task-related Member Variables
- // -----------------------------------------------------------------
+ Error GetFileLoadAddress(const llvm::StringRef &file_name,
+ lldb::addr_t &load_addr) override;
- // The task port for the inferior process.
- mutable task_t m_task;
+ NativeThreadDarwinSP GetThreadByID(lldb::tid_t id);
- // True if the inferior process did an exec since we started
- // monitoring it.
- bool m_did_exec;
+ task_t GetTask() const { return m_task; }
- // The CPU type of this process.
- mutable cpu_type_t m_cpu_type;
+ // -----------------------------------------------------------------
+ // Interface used by NativeRegisterContext-derived classes.
+ // -----------------------------------------------------------------
+ static Error PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr,
+ void *data = nullptr, size_t data_size = 0,
+ long *result = nullptr);
- // -----------------------------------------------------------------
- /// Exception/Signal Handling Member Variables
- // -----------------------------------------------------------------
+ bool SupportHardwareSingleStepping() const;
- // Exception port on which we will receive child exceptions
- mach_port_t m_exception_port;
+protected:
+ // -----------------------------------------------------------------
+ // NativeProcessProtocol protected interface
+ // -----------------------------------------------------------------
+ Error
+ GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint,
+ size_t &actual_opcode_size,
+ const uint8_t *&trap_opcode_bytes) override;
- // Saved state of the child exception port prior to us installing
- // our own intercepting port.
- MachException::PortInfo m_exc_port_info;
+private:
+ // -----------------------------------------------------------------
+ /// Mach task-related Member Variables
+ // -----------------------------------------------------------------
- // The thread that runs the Mach exception read and reply handler.
- pthread_t m_exception_thread;
+ // The task port for the inferior process.
+ mutable task_t m_task;
- // TODO see if we can remove this if we get the exception collection
- // and distribution to happen in a single-threaded fashion.
- std::recursive_mutex m_exception_messages_mutex;
+ // True if the inferior process did an exec since we started
+ // monitoring it.
+ bool m_did_exec;
- // A collection of exception messages caught when listening to the
- // exception port.
- MachException::Message::collection m_exception_messages;
+ // The CPU type of this process.
+ mutable cpu_type_t m_cpu_type;
- // When we call MachProcess::Interrupt(), we want to send this
- // signal (if non-zero).
- int m_sent_interrupt_signo;
+ // -----------------------------------------------------------------
+ /// Exception/Signal Handling Member Variables
+ // -----------------------------------------------------------------
- // If we resume the process and still haven't received our
- // interrupt signal (if this is non-zero).
- int m_auto_resume_signo;
+ // Exception port on which we will receive child exceptions
+ mach_port_t m_exception_port;
- // -----------------------------------------------------------------
- /// Thread-related Member Variables
- // -----------------------------------------------------------------
- NativeThreadListDarwin m_thread_list;
- ResumeActionList m_thread_actions;
+ // Saved state of the child exception port prior to us installing
+ // our own intercepting port.
+ MachException::PortInfo m_exc_port_info;
- // -----------------------------------------------------------------
- /// Process Lifetime Member Variable
- // -----------------------------------------------------------------
+ // The thread that runs the Mach exception read and reply handler.
+ pthread_t m_exception_thread;
- // The pipe over which the waitpid thread and the main loop will
- // communicate.
- Pipe m_waitpid_pipe;
-
- // The thread that runs the waitpid handler.
- pthread_t m_waitpid_thread;
-
- // waitpid reader callback handle.
- MainLoop::ReadHandleUP m_waitpid_reader_handle;
+ // TODO see if we can remove this if we get the exception collection
+ // and distribution to happen in a single-threaded fashion.
+ std::recursive_mutex m_exception_messages_mutex;
+
+ // A collection of exception messages caught when listening to the
+ // exception port.
+ MachException::Message::collection m_exception_messages;
+
+ // When we call MachProcess::Interrupt(), we want to send this
+ // signal (if non-zero).
+ int m_sent_interrupt_signo;
+
+ // If we resume the process and still haven't received our
+ // interrupt signal (if this is non-zero).
+ int m_auto_resume_signo;
+
+ // -----------------------------------------------------------------
+ /// Thread-related Member Variables
+ // -----------------------------------------------------------------
+ NativeThreadListDarwin m_thread_list;
+ ResumeActionList m_thread_actions;
+
+ // -----------------------------------------------------------------
+ /// Process Lifetime Member Variable
+ // -----------------------------------------------------------------
+
+ // The pipe over which the waitpid thread and the main loop will
+ // communicate.
+ Pipe m_waitpid_pipe;
+
+ // The thread that runs the waitpid handler.
+ pthread_t m_waitpid_thread;
+
+ // waitpid reader callback handle.
+ MainLoop::ReadHandleUP m_waitpid_reader_handle;
#if 0
ArchSpec m_arch;
@@ -249,158 +210,116 @@ namespace lldb_private {
m_threads_stepping_with_breakpoint;
#endif
- // -----------------------------------------------------------------
- // Private Instance Methods
- // -----------------------------------------------------------------
- NativeProcessDarwin(lldb::pid_t pid, int pty_master_fd);
+ // -----------------------------------------------------------------
+ // Private Instance Methods
+ // -----------------------------------------------------------------
+ NativeProcessDarwin(lldb::pid_t pid, int pty_master_fd);
- // -----------------------------------------------------------------
- /// Finalize the launch.
- ///
- /// This method associates the NativeProcessDarwin instance with
- /// the host process that was just launched. It peforms actions
- /// like attaching a listener to the inferior exception port,
- /// ptracing the process, and the like.
- ///
- /// @param[in] launch_flavor
- /// The launch flavor that was used to launch the process.
- ///
- /// @param[in] main_loop
- /// The main loop that will run the process monitor. Work
- /// that needs to be done (e.g. reading files) gets registered
- /// here along with callbacks to process the work.
- ///
- /// @return
- /// Any error that occurred during the aforementioned
- /// operations. Failure here will force termination of the
- /// launched process and debugging session.
- // -----------------------------------------------------------------
- Error
- FinalizeLaunch(LaunchFlavor launch_flavor, MainLoop &main_loop);
+ // -----------------------------------------------------------------
+ /// Finalize the launch.
+ ///
+ /// This method associates the NativeProcessDarwin instance with
+ /// the host process that was just launched. It peforms actions
+ /// like attaching a listener to the inferior exception port,
+ /// ptracing the process, and the like.
+ ///
+ /// @param[in] launch_flavor
+ /// The launch flavor that was used to launch the process.
+ ///
+ /// @param[in] main_loop
+ /// The main loop that will run the process monitor. Work
+ /// that needs to be done (e.g. reading files) gets registered
+ /// here along with callbacks to process the work.
+ ///
+ /// @return
+ /// Any error that occurred during the aforementioned
+ /// operations. Failure here will force termination of the
+ /// launched process and debugging session.
+ // -----------------------------------------------------------------
+ Error FinalizeLaunch(LaunchFlavor launch_flavor, MainLoop &main_loop);
- Error
- SaveExceptionPortInfo();
+ Error SaveExceptionPortInfo();
- void
- ExceptionMessageReceived(const MachException::Message &message);
+ void ExceptionMessageReceived(const MachException::Message &message);
- void
- MaybeRaiseThreadPriority();
+ void MaybeRaiseThreadPriority();
- Error
- StartExceptionThread();
+ Error StartExceptionThread();
- Error
- SendInferiorExitStatusToMainLoop(::pid_t pid, int status);
+ Error SendInferiorExitStatusToMainLoop(::pid_t pid, int status);
- Error
- HandleWaitpidResult();
+ Error HandleWaitpidResult();
- bool
- ProcessUsingSpringBoard() const;
+ bool ProcessUsingSpringBoard() const;
- bool
- ProcessUsingBackBoard() const;
+ bool ProcessUsingBackBoard() const;
- static void*
- ExceptionThread(void *arg);
+ static void *ExceptionThread(void *arg);
- void*
- DoExceptionThread();
+ void *DoExceptionThread();
- lldb::addr_t
- GetDYLDAllImageInfosAddress(Error &error) const;
+ lldb::addr_t GetDYLDAllImageInfosAddress(Error &error) const;
- static uint32_t
- GetCPUTypeForLocalProcess(::pid_t pid);
+ static uint32_t GetCPUTypeForLocalProcess(::pid_t pid);
- uint32_t
- GetCPUType() const;
+ uint32_t GetCPUType() const;
- task_t
- ExceptionMessageBundleComplete();
+ task_t ExceptionMessageBundleComplete();
- void
- StartSTDIOThread();
+ void StartSTDIOThread();
- Error
- StartWaitpidThread(MainLoop &main_loop);
+ Error StartWaitpidThread(MainLoop &main_loop);
- static void*
- WaitpidThread(void *arg);
+ static void *WaitpidThread(void *arg);
- void*
- DoWaitpidThread();
+ void *DoWaitpidThread();
- task_t
- TaskPortForProcessID(Error &error, bool force = false) const;
+ task_t TaskPortForProcessID(Error &error, bool force = false) const;
- /// Attaches to an existing process. Forms the
- /// implementation of Process::DoAttach.
- void
- AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Error &error);
+ /// Attaches to an existing process. Forms the
+ /// implementation of Process::DoAttach.
+ void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Error &error);
- ::pid_t
- Attach(lldb::pid_t pid, Error &error);
+ ::pid_t Attach(lldb::pid_t pid, Error &error);
- Error
- PrivateResume();
+ Error PrivateResume();
- Error
- ReplyToAllExceptions();
+ Error ReplyToAllExceptions();
- Error
- ResumeTask();
+ Error ResumeTask();
- bool
- IsTaskValid() const;
+ bool IsTaskValid() const;
- bool
- IsTaskValid(task_t task) const;
+ bool IsTaskValid(task_t task) const;
- mach_port_t
- GetExceptionPort() const;
+ mach_port_t GetExceptionPort() const;
- bool
- IsExceptionPortValid () const;
+ bool IsExceptionPortValid() const;
- Error
- GetTaskBasicInfo(task_t task, struct task_basic_info *info) const;
+ Error GetTaskBasicInfo(task_t task, struct task_basic_info *info) const;
- Error
- SuspendTask();
+ Error SuspendTask();
- static Error
- SetDefaultPtraceOpts(const lldb::pid_t);
+ static Error SetDefaultPtraceOpts(const lldb::pid_t);
- static void *
- MonitorThread(void *baton);
+ static void *MonitorThread(void *baton);
- void
- MonitorCallback(lldb::pid_t pid, bool exited, int signal,
- int status);
+ void MonitorCallback(lldb::pid_t pid, bool exited, int signal, int status);
- void
- WaitForNewThread(::pid_t tid);
+ void WaitForNewThread(::pid_t tid);
- void
- MonitorSIGTRAP(const siginfo_t &info, NativeThreadDarwin &thread);
+ void MonitorSIGTRAP(const siginfo_t &info, NativeThreadDarwin &thread);
- void
- MonitorTrace(NativeThreadDarwin &thread);
+ void MonitorTrace(NativeThreadDarwin &thread);
- void
- MonitorBreakpoint(NativeThreadDarwin &thread);
+ void MonitorBreakpoint(NativeThreadDarwin &thread);
- void
- MonitorWatchpoint(NativeThreadDarwin &thread, uint32_t wp_index);
+ void MonitorWatchpoint(NativeThreadDarwin &thread, uint32_t wp_index);
- void
- MonitorSignal(const siginfo_t &info, NativeThreadDarwin &thread,
- bool exited);
+ void MonitorSignal(const siginfo_t &info, NativeThreadDarwin &thread,
+ bool exited);
- Error
- SetupSoftwareSingleStepping(NativeThreadDarwin &thread);
+ Error SetupSoftwareSingleStepping(NativeThreadDarwin &thread);
#if 0
static ::ProcessMessage::CrashReason
@@ -416,64 +335,50 @@ namespace lldb_private {
GetCrashReasonForSIGBUS(const siginfo_t *info);
#endif
- bool
- HasThreadNoLock(lldb::tid_t thread_id);
-
- bool
- StopTrackingThread(lldb::tid_t thread_id);
-
- NativeThreadDarwinSP
- AddThread(lldb::tid_t thread_id);
-
- Error
- GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size);
-
- Error
- FixupBreakpointPCAsNeeded(NativeThreadDarwin &thread);
-
- /// Writes a siginfo_t structure corresponding to the given thread
- /// ID to the memory region pointed to by @p siginfo.
- Error
- GetSignalInfo(lldb::tid_t tid, void *siginfo);
-
- /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
- /// corresponding to the given thread ID to the memory pointed to
- /// by @p message.
- Error
- GetEventMessage(lldb::tid_t tid, unsigned long *message);
-
- void
- NotifyThreadDeath(lldb::tid_t tid);
-
- Error
- Detach(lldb::tid_t tid);
-
-
- // This method is requests a stop on all threads which are still
- // running. It sets up a deferred delegate notification, which will
- // fire once threads report as stopped. The triggerring_tid will be
- // set as the current thread (main stop reason).
- void
- StopRunningThreads(lldb::tid_t triggering_tid);
-
- // Notify the delegate if all threads have stopped.
- void SignalIfAllThreadsStopped();
-
- // Resume the given thread, optionally passing it the given signal.
- // The type of resume operation (continue, single-step) depends on
- // the state parameter.
- Error
- ResumeThread(NativeThreadDarwin &thread, lldb::StateType state,
- int signo);
-
- void
- ThreadWasCreated(NativeThreadDarwin &thread);
-
- void
- SigchldHandler();
- };
-
- } // namespace process_darwin
+ bool HasThreadNoLock(lldb::tid_t thread_id);
+
+ bool StopTrackingThread(lldb::tid_t thread_id);
+
+ NativeThreadDarwinSP AddThread(lldb::tid_t thread_id);
+
+ Error GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size);
+
+ Error FixupBreakpointPCAsNeeded(NativeThreadDarwin &thread);
+
+ /// Writes a siginfo_t structure corresponding to the given thread
+ /// ID to the memory region pointed to by @p siginfo.
+ Error GetSignalInfo(lldb::tid_t tid, void *siginfo);
+
+ /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
+ /// corresponding to the given thread ID to the memory pointed to
+ /// by @p message.
+ Error GetEventMessage(lldb::tid_t tid, unsigned long *message);
+
+ void NotifyThreadDeath(lldb::tid_t tid);
+
+ Error Detach(lldb::tid_t tid);
+
+ // This method is requests a stop on all threads which are still
+ // running. It sets up a deferred delegate notification, which will
+ // fire once threads report as stopped. The triggerring_tid will be
+ // set as the current thread (main stop reason).
+ void StopRunningThreads(lldb::tid_t triggering_tid);
+
+ // Notify the delegate if all threads have stopped.
+ void SignalIfAllThreadsStopped();
+
+ // Resume the given thread, optionally passing it the given signal.
+ // The type of resume operation (continue, single-step) depends on
+ // the state parameter.
+ Error ResumeThread(NativeThreadDarwin &thread, lldb::StateType state,
+ int signo);
+
+ void ThreadWasCreated(NativeThreadDarwin &thread);
+
+ void SigchldHandler();
+};
+
+} // namespace process_darwin
} // namespace lldb_private
#endif /* NativeProcessDarwin_h */
diff --git a/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp b/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp
index 08d1a8da92b..5e7f9ae7e6f 100644
--- a/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp
+++ b/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp
@@ -21,117 +21,94 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_darwin;
-uint64_t
-NativeThreadDarwin::GetGloballyUniqueThreadIDForMachPortID(
- ::thread_t mach_port_id)
-{
- thread_identifier_info_data_t tident;
- mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT;
-
- auto mach_err = ::thread_info(mach_port_id, THREAD_IDENTIFIER_INFO,
- (thread_info_t) &tident, &tident_count);
- if (mach_err != KERN_SUCCESS)
- {
- // When we fail to get thread info for the supposed port, assume it is
- // really a globally unique thread id already, or return the best thing
- // we can, which is the thread port.
- return mach_port_id;
- }
- return tident.thread_id;
+uint64_t NativeThreadDarwin::GetGloballyUniqueThreadIDForMachPortID(
+ ::thread_t mach_port_id) {
+ thread_identifier_info_data_t tident;
+ mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT;
+
+ auto mach_err = ::thread_info(mach_port_id, THREAD_IDENTIFIER_INFO,
+ (thread_info_t)&tident, &tident_count);
+ if (mach_err != KERN_SUCCESS) {
+ // When we fail to get thread info for the supposed port, assume it is
+ // really a globally unique thread id already, or return the best thing
+ // we can, which is the thread port.
+ return mach_port_id;
+ }
+ return tident.thread_id;
}
NativeThreadDarwin::NativeThreadDarwin(NativeProcessDarwin *process,
bool is_64_bit,
lldb::tid_t unique_thread_id,
- ::thread_t mach_thread_port) :
- NativeThreadProtocol(process, unique_thread_id),
- m_mach_thread_port(mach_thread_port),
- m_basic_info(),
- m_proc_threadinfo()
-{
-}
-
-bool
-NativeThreadDarwin::GetIdentifierInfo()
-{
- // Don't try to get the thread info once and cache it for the life of the thread. It changes over time, for instance
- // if the thread name changes, then the thread_handle also changes... So you have to refetch it every time.
- mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
- kern_return_t kret = ::thread_info(m_mach_thread_port,
- THREAD_IDENTIFIER_INFO,
- (thread_info_t) &m_ident_info, &count);
- return kret == KERN_SUCCESS;
-
- return false;
+ ::thread_t mach_thread_port)
+ : NativeThreadProtocol(process, unique_thread_id),
+ m_mach_thread_port(mach_thread_port), m_basic_info(),
+ m_proc_threadinfo() {}
+
+bool NativeThreadDarwin::GetIdentifierInfo() {
+ // Don't try to get the thread info once and cache it for the life of the
+ // thread. It changes over time, for instance
+ // if the thread name changes, then the thread_handle also changes... So you
+ // have to refetch it every time.
+ mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
+ kern_return_t kret = ::thread_info(m_mach_thread_port, THREAD_IDENTIFIER_INFO,
+ (thread_info_t)&m_ident_info, &count);
+ return kret == KERN_SUCCESS;
+
+ return false;
}
-std::string
-NativeThreadDarwin::GetName()
-{
- std::string name;
+std::string NativeThreadDarwin::GetName() {
+ std::string name;
- if (GetIdentifierInfo())
- {
- auto process_sp = GetProcess();
- if (!process_sp)
- {
- name = "<unavailable>";
- return name;
- }
+ if (GetIdentifierInfo()) {
+ auto process_sp = GetProcess();
+ if (!process_sp) {
+ name = "<unavailable>";
+ return name;
+ }
- int len = ::proc_pidinfo(process_sp->GetID(), PROC_PIDTHREADINFO,
- m_ident_info.thread_handle, &m_proc_threadinfo,
- sizeof(m_proc_threadinfo));
+ int len = ::proc_pidinfo(process_sp->GetID(), PROC_PIDTHREADINFO,
+ m_ident_info.thread_handle, &m_proc_threadinfo,
+ sizeof(m_proc_threadinfo));
- if (len && m_proc_threadinfo.pth_name[0])
- name = m_proc_threadinfo.pth_name;
- }
- return name;
+ if (len && m_proc_threadinfo.pth_name[0])
+ name = m_proc_threadinfo.pth_name;
+ }
+ return name;
}
-lldb::StateType
-NativeThreadDarwin::GetState()
-{
- // TODO implement
- return eStateInvalid;
+lldb::StateType NativeThreadDarwin::GetState() {
+ // TODO implement
+ return eStateInvalid;
}
-bool
-NativeThreadDarwin::GetStopReason(ThreadStopInfo &stop_info,
- std::string& description)
-{
- // TODO implement
- return false;
+bool NativeThreadDarwin::GetStopReason(ThreadStopInfo &stop_info,
+ std::string &description) {
+ // TODO implement
+ return false;
}
-NativeRegisterContextSP
-NativeThreadDarwin::GetRegisterContext()
-{
- // TODO implement
- return NativeRegisterContextSP();
+NativeRegisterContextSP NativeThreadDarwin::GetRegisterContext() {
+ // TODO implement
+ return NativeRegisterContextSP();
}
-Error
-NativeThreadDarwin::SetWatchpoint(lldb::addr_t addr, size_t size,
- uint32_t watch_flags, bool hardware)
-{
- Error error;
- error.SetErrorString("not yet implemented");
- return error;
+Error NativeThreadDarwin::SetWatchpoint(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags, bool hardware) {
+ Error error;
+ error.SetErrorString("not yet implemented");
+ return error;
}
-Error
-NativeThreadDarwin::RemoveWatchpoint(lldb::addr_t addr)
-{
- Error error;
- error.SetErrorString("not yet implemented");
- return error;
+Error NativeThreadDarwin::RemoveWatchpoint(lldb::addr_t addr) {
+ Error error;
+ error.SetErrorString("not yet implemented");
+ return error;
}
-void
-NativeThreadDarwin::Dump(Stream &stream) const
-{
- // This is what we really want once we have the thread class wired up.
+void NativeThreadDarwin::Dump(Stream &stream) const {
+// This is what we really want once we have the thread class wired up.
#if 0
DNBLogThreaded("[%3u] #%3u tid: 0x%8.8" PRIx64 ", pc: 0x%16.16" PRIx64 ", sp: 0x%16.16" PRIx64 ", user: %d.%6.6d, system: %d.%6.6d, cpu: %2d, policy: %2d, run_state: %2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d",
index,
@@ -150,16 +127,14 @@ NativeThreadDarwin::Dump(Stream &stream) const
m_basic_info.sleep_time);
#else
- // Here's all we have right now.
- stream.Printf("tid: 0x%8.8" PRIx64 ", thread port: 0x%4.4x",
- GetID(), m_mach_thread_port);
+ // Here's all we have right now.
+ stream.Printf("tid: 0x%8.8" PRIx64 ", thread port: 0x%4.4x", GetID(),
+ m_mach_thread_port);
#endif
}
-bool
-NativeThreadDarwin::NotifyException(MachException::Data &exc)
-{
- // TODO implement this.
+bool NativeThreadDarwin::NotifyException(MachException::Data &exc) {
+// TODO implement this.
#if 0
// Allow the arch specific protocol to process (MachException::Data &)exc
// first before possible reassignment of m_stop_exception with exc.
@@ -182,15 +157,13 @@ NativeThreadDarwin::NotifyException(MachException::Data &exc)
return handled;
#else
- // Pretend we handled it.
- return true;
+ // Pretend we handled it.
+ return true;
#endif
}
-bool
-NativeThreadDarwin::ShouldStop(bool &step_more) const
-{
- // TODO: implement this
+bool NativeThreadDarwin::ShouldStop(bool &step_more) const {
+// TODO: implement this
#if 0
// See if this thread is at a breakpoint?
DNBBreakpoint *bp = CurrentBreakpoint();
@@ -229,14 +202,12 @@ NativeThreadDarwin::ShouldStop(bool &step_more) const
}
return false;
#else
- return false;
+ return false;
#endif
}
-void
-NativeThreadDarwin::ThreadDidStop()
-{
- // TODO implement this.
+void NativeThreadDarwin::ThreadDidStop() {
+// TODO implement this.
#if 0
// This thread has existed prior to resuming under debug nub control,
// and has just been stopped. Do any cleanup that needs to be done
@@ -267,58 +238,47 @@ NativeThreadDarwin::ThreadDidStop()
#endif
}
-bool
-NativeThreadDarwin::MachPortNumberIsValid(::thread_t thread)
-{
- return thread != (::thread_t)(0);
+bool NativeThreadDarwin::MachPortNumberIsValid(::thread_t thread) {
+ return thread != (::thread_t)(0);
}
-const struct thread_basic_info *
-NativeThreadDarwin::GetBasicInfo() const
-{
- if (GetBasicInfo(m_mach_thread_port, &m_basic_info))
- return &m_basic_info;
- return NULL;
+const struct thread_basic_info *NativeThreadDarwin::GetBasicInfo() const {
+ if (GetBasicInfo(m_mach_thread_port, &m_basic_info))
+ return &m_basic_info;
+ return NULL;
}
-bool
-NativeThreadDarwin::GetBasicInfo(::thread_t thread,
- struct thread_basic_info *basicInfoPtr)
-{
- if (MachPortNumberIsValid(thread))
- {
- unsigned int info_count = THREAD_BASIC_INFO_COUNT;
- kern_return_t err = ::thread_info (thread, THREAD_BASIC_INFO, (thread_info_t) basicInfoPtr, &info_count);
- if (err == KERN_SUCCESS)
- return true;
- }
- ::memset (basicInfoPtr, 0, sizeof (struct thread_basic_info));
- return false;
+bool NativeThreadDarwin::GetBasicInfo(::thread_t thread,
+ struct thread_basic_info *basicInfoPtr) {
+ if (MachPortNumberIsValid(thread)) {
+ unsigned int info_count = THREAD_BASIC_INFO_COUNT;
+ kern_return_t err = ::thread_info(thread, THREAD_BASIC_INFO,
+ (thread_info_t)basicInfoPtr, &info_count);
+ if (err == KERN_SUCCESS)
+ return true;
+ }
+ ::memset(basicInfoPtr, 0, sizeof(struct thread_basic_info));
+ return false;
}
-bool
-NativeThreadDarwin::IsUserReady() const
-{
- if (m_basic_info.run_state == 0)
- GetBasicInfo();
+bool NativeThreadDarwin::IsUserReady() const {
+ if (m_basic_info.run_state == 0)
+ GetBasicInfo();
- switch (m_basic_info.run_state)
- {
- default:
- case TH_STATE_UNINTERRUPTIBLE:
- break;
-
- case TH_STATE_RUNNING:
- case TH_STATE_STOPPED:
- case TH_STATE_WAITING:
- case TH_STATE_HALTED:
- return true;
- }
- return false;
+ switch (m_basic_info.run_state) {
+ default:
+ case TH_STATE_UNINTERRUPTIBLE:
+ break;
+
+ case TH_STATE_RUNNING:
+ case TH_STATE_STOPPED:
+ case TH_STATE_WAITING:
+ case TH_STATE_HALTED:
+ return true;
+ }
+ return false;
}
-NativeProcessDarwinSP
-NativeThreadDarwin::GetNativeProcessDarwinSP()
-{
- return std::static_pointer_cast<NativeProcessDarwin>(GetProcess());
+NativeProcessDarwinSP NativeThreadDarwin::GetNativeProcessDarwinSP() {
+ return std::static_pointer_cast<NativeProcessDarwin>(GetProcess());
}
diff --git a/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.h b/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.h
index efdf79ac3e0..b8d9089e673 100644
--- a/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.h
+++ b/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.h
@@ -21,8 +21,8 @@
#include <string>
// LLDB includes
-#include "lldb/lldb-private-forward.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "lldb/lldb-private-forward.h"
#include "MachException.h"
@@ -34,168 +34,130 @@ using NativeProcessDarwinSP = std::shared_ptr<NativeProcessDarwin>;
class NativeThreadListDarwin;
-class NativeThreadDarwin : public NativeThreadProtocol
-{
- friend class NativeProcessDarwin;
- friend class NativeThreadListDarwin;
+class NativeThreadDarwin : public NativeThreadProtocol {
+ friend class NativeProcessDarwin;
+ friend class NativeThreadListDarwin;
public:
+ static uint64_t
+ GetGloballyUniqueThreadIDForMachPortID(::thread_t mach_port_id);
- static uint64_t
- GetGloballyUniqueThreadIDForMachPortID(::thread_t mach_port_id);
-
- NativeThreadDarwin(NativeProcessDarwin *process, bool is_64_bit,
- lldb::tid_t unique_thread_id = 0,
- ::thread_t mach_thread_port = 0);
+ NativeThreadDarwin(NativeProcessDarwin *process, bool is_64_bit,
+ lldb::tid_t unique_thread_id = 0,
+ ::thread_t mach_thread_port = 0);
- // -----------------------------------------------------------------
- // NativeThreadProtocol Interface
- // -----------------------------------------------------------------
- std::string
- GetName() override;
+ // -----------------------------------------------------------------
+ // NativeThreadProtocol Interface
+ // -----------------------------------------------------------------
+ std::string GetName() override;
- lldb::StateType
- GetState () override;
+ lldb::StateType GetState() override;
- bool
- GetStopReason(ThreadStopInfo &stop_info,
- std::string& description) override;
+ bool GetStopReason(ThreadStopInfo &stop_info,
+ std::string &description) override;
- NativeRegisterContextSP
- GetRegisterContext() override;
+ NativeRegisterContextSP GetRegisterContext() override;
- Error
- SetWatchpoint(lldb::addr_t addr, size_t size,
- uint32_t watch_flags, bool hardware) override;
+ Error SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags,
+ bool hardware) override;
- Error
- RemoveWatchpoint(lldb::addr_t addr) override;
+ Error RemoveWatchpoint(lldb::addr_t addr) override;
- // -----------------------------------------------------------------
- // New methods that are fine for others to call.
- // -----------------------------------------------------------------
- void
- Dump(Stream &stream) const;
+ // -----------------------------------------------------------------
+ // New methods that are fine for others to call.
+ // -----------------------------------------------------------------
+ void Dump(Stream &stream) const;
private:
- // -----------------------------------------------------------------
- // Interface for friend classes
- // -----------------------------------------------------------------
+ // -----------------------------------------------------------------
+ // Interface for friend classes
+ // -----------------------------------------------------------------
- /// Resumes the thread. If @p signo is anything but
- /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
- Error
- Resume(uint32_t signo);
+ /// Resumes the thread. If @p signo is anything but
+ /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+ Error Resume(uint32_t signo);
- /// Single steps the thread. If @p signo is anything but
- /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
- Error
- SingleStep(uint32_t signo);
+ /// Single steps the thread. If @p signo is anything but
+ /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+ Error SingleStep(uint32_t signo);
- bool
- NotifyException(MachException::Data &exc);
+ bool NotifyException(MachException::Data &exc);
- bool
- ShouldStop(bool &step_more) const;
+ bool ShouldStop(bool &step_more) const;
- void
- ThreadDidStop();
+ void ThreadDidStop();
- void
- SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
+ void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
- /// Return true if the thread is stopped.
- /// If stopped by a signal, indicate the signo in the signo
- /// argument. Otherwise, return LLDB_INVALID_SIGNAL_NUMBER.
- bool
- IsStopped (int *signo);
+ /// Return true if the thread is stopped.
+ /// If stopped by a signal, indicate the signo in the signo
+ /// argument. Otherwise, return LLDB_INVALID_SIGNAL_NUMBER.
+ bool IsStopped(int *signo);
- const struct thread_basic_info *
- GetBasicInfo() const;
+ const struct thread_basic_info *GetBasicInfo() const;
- static bool
- GetBasicInfo(::thread_t thread, struct thread_basic_info *basicInfoPtr);
+ static bool GetBasicInfo(::thread_t thread,
+ struct thread_basic_info *basicInfoPtr);
- bool
- IsUserReady() const;
+ bool IsUserReady() const;
- void
- SetStoppedByExec ();
+ void SetStoppedByExec();
- void
- SetStoppedByBreakpoint ();
+ void SetStoppedByBreakpoint();
- void
- SetStoppedByWatchpoint (uint32_t wp_index);
+ void SetStoppedByWatchpoint(uint32_t wp_index);
- bool
- IsStoppedAtBreakpoint ();
+ bool IsStoppedAtBreakpoint();
- bool
- IsStoppedAtWatchpoint ();
+ bool IsStoppedAtWatchpoint();
- void
- SetStoppedByTrace ();
+ void SetStoppedByTrace();
- void
- SetStoppedWithNoReason ();
+ void SetStoppedWithNoReason();
- void
- SetExited ();
+ void SetExited();
- Error
- RequestStop ();
+ Error RequestStop();
- // -------------------------------------------------------------------------
- /// Return the mach thread port number for this thread.
- ///
- /// @return
- /// The mach port number for this thread. Returns NULL_THREAD
- /// when the thread is invalid.
- // -------------------------------------------------------------------------
- thread_t
- GetMachPortNumber() const
- {
- return m_mach_thread_port;
- }
+ // -------------------------------------------------------------------------
+ /// Return the mach thread port number for this thread.
+ ///
+ /// @return
+ /// The mach port number for this thread. Returns NULL_THREAD
+ /// when the thread is invalid.
+ // -------------------------------------------------------------------------
+ thread_t GetMachPortNumber() const { return m_mach_thread_port; }
- static bool
- MachPortNumberIsValid(::thread_t thread);
+ static bool MachPortNumberIsValid(::thread_t thread);
- // ---------------------------------------------------------------------
- // Private interface
- // ---------------------------------------------------------------------
- bool
- GetIdentifierInfo();
+ // ---------------------------------------------------------------------
+ // Private interface
+ // ---------------------------------------------------------------------
+ bool GetIdentifierInfo();
- void
- MaybeLogStateChange (lldb::StateType new_state);
+ void MaybeLogStateChange(lldb::StateType new_state);
- NativeProcessDarwinSP
- GetNativeProcessDarwinSP();
+ NativeProcessDarwinSP GetNativeProcessDarwinSP();
- void
- SetStopped();
+ void SetStopped();
- inline void
- MaybePrepareSingleStepWorkaround();
+ inline void MaybePrepareSingleStepWorkaround();
- inline void
- MaybeCleanupSingleStepWorkaround();
+ inline void MaybeCleanupSingleStepWorkaround();
- // -----------------------------------------------------------------
- // Member Variables
- // -----------------------------------------------------------------
+ // -----------------------------------------------------------------
+ // Member Variables
+ // -----------------------------------------------------------------
- // The mach thread port for the thread.
- ::thread_t m_mach_thread_port;
+ // The mach thread port for the thread.
+ ::thread_t m_mach_thread_port;
- // The most recently-retrieved thread basic info.
- mutable ::thread_basic_info m_basic_info;
+ // The most recently-retrieved thread basic info.
+ mutable ::thread_basic_info m_basic_info;
- struct proc_threadinfo m_proc_threadinfo;
+ struct proc_threadinfo m_proc_threadinfo;
- thread_identifier_info_data_t m_ident_info;
+ thread_identifier_info_data_t m_ident_info;
#if 0
lldb::StateType m_state;
diff --git a/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp b/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp
index 034c0c9f1fa..aa9b0415765 100644
--- a/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp
+++ b/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp
@@ -1,4 +1,5 @@
-//===-- NativeThreadListDarwin.cpp ------------------------------------*- C++ -*-===//
+//===-- NativeThreadListDarwin.cpp ------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -31,16 +32,10 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_darwin;
-NativeThreadListDarwin::NativeThreadListDarwin() :
- m_threads(),
- m_threads_mutex(),
- m_is_64_bit(false)
-{
-}
+NativeThreadListDarwin::NativeThreadListDarwin()
+ : m_threads(), m_threads_mutex(), m_is_64_bit(false) {}
-NativeThreadListDarwin::~NativeThreadListDarwin()
-{
-}
+NativeThreadListDarwin::~NativeThreadListDarwin() {}
// These methods will be accessed directly from NativeThreadDarwin
#if 0
@@ -155,41 +150,33 @@ NativeThreadListDarwin::GetThreadInfo (nub_thread_t tid) const
#endif
NativeThreadDarwinSP
-NativeThreadListDarwin::GetThreadByID(lldb::tid_t tid) const
-{
- std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- for (auto thread_sp : m_threads)
- {
- if (thread_sp && (thread_sp->GetID() == tid))
- return thread_sp;
- }
- return NativeThreadDarwinSP();
-}
-
-NativeThreadDarwinSP
-NativeThreadListDarwin::GetThreadByMachPortNumber(::thread_t mach_port_number)
- const
-{
- std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- for (auto thread_sp : m_threads)
- {
- if (thread_sp && (thread_sp->GetMachPortNumber() == mach_port_number))
- return thread_sp;
- }
- return NativeThreadDarwinSP();
-}
-
-lldb::tid_t
-NativeThreadListDarwin::GetThreadIDByMachPortNumber(::thread_t mach_port_number)
- const
-{
- std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- for (auto thread_sp : m_threads)
- {
- if (thread_sp && (thread_sp->GetMachPortNumber() == mach_port_number))
- return thread_sp->GetID();
- }
- return LLDB_INVALID_THREAD_ID;
+NativeThreadListDarwin::GetThreadByID(lldb::tid_t tid) const {
+ std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
+ for (auto thread_sp : m_threads) {
+ if (thread_sp && (thread_sp->GetID() == tid))
+ return thread_sp;
+ }
+ return NativeThreadDarwinSP();
+}
+
+NativeThreadDarwinSP NativeThreadListDarwin::GetThreadByMachPortNumber(
+ ::thread_t mach_port_number) const {
+ std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
+ for (auto thread_sp : m_threads) {
+ if (thread_sp && (thread_sp->GetMachPortNumber() == mach_port_number))
+ return thread_sp;
+ }
+ return NativeThreadDarwinSP();
+}
+
+lldb::tid_t NativeThreadListDarwin::GetThreadIDByMachPortNumber(
+ ::thread_t mach_port_number) const {
+ std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
+ for (auto thread_sp : m_threads) {
+ if (thread_sp && (thread_sp->GetMachPortNumber() == mach_port_number))
+ return thread_sp->GetID();
+ }
+ return LLDB_INVALID_THREAD_ID;
}
// TODO implement
@@ -267,11 +254,9 @@ NativeThreadListDarwin::RestoreRegisterState (nub_thread_t tid, uint32_t save_id
}
#endif
-size_t
-NativeThreadListDarwin::GetNumberOfThreads() const
-{
- std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- return static_cast<size_t>(m_threads.size());
+size_t NativeThreadListDarwin::GetNumberOfThreads() const {
+ std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
+ return static_cast<size_t>(m_threads.size());
}
// TODO implement
@@ -297,149 +282,129 @@ NativeThreadListDarwin::CurrentThreadID ( )
#endif
-bool
-NativeThreadListDarwin::NotifyException(MachException::Data &exc)
-{
- auto thread_sp = GetThreadByMachPortNumber(exc.thread_port);
- if (thread_sp)
- {
- thread_sp->NotifyException(exc);
- return true;
+bool NativeThreadListDarwin::NotifyException(MachException::Data &exc) {
+ auto thread_sp = GetThreadByMachPortNumber(exc.thread_port);
+ if (thread_sp) {
+ thread_sp->NotifyException(exc);
+ return true;
+ }
+ return false;
+}
+
+void NativeThreadListDarwin::Clear() {
+ std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
+ m_threads.clear();
+}
+
+uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process,
+ bool update,
+ collection *new_threads) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
+ if (log)
+ log->Printf("NativeThreadListDarwin::%s() (pid = %" PRIu64 ", update = "
+ "%u) process stop count = %u",
+ __FUNCTION__, process.GetID(), update, process.GetStopID());
+
+ if (process.GetStopID() == 0) {
+ // On our first stop, we'll record details like 32/64 bitness and
+ // select the proper architecture implementation.
+ //
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)process.GetID()};
+
+ struct kinfo_proc processInfo;
+ size_t bufsize = sizeof(processInfo);
+ if ((sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo,
+ &bufsize, NULL, 0) == 0) &&
+ (bufsize > 0)) {
+ if (processInfo.kp_proc.p_flag & P_LP64)
+ m_is_64_bit = true;
}
- return false;
-}
-
-void
-NativeThreadListDarwin::Clear()
-{
- std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- m_threads.clear();
-}
-
-uint32_t
-NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process,
- bool update,
- collection *new_threads)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
-
- std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- if (log)
- log->Printf("NativeThreadListDarwin::%s() (pid = %" PRIu64 ", update = "
- "%u) process stop count = %u", __FUNCTION__,
- process.GetID(), update, process.GetStopID());
-
- if (process.GetStopID() == 0)
- {
- // On our first stop, we'll record details like 32/64 bitness and
- // select the proper architecture implementation.
- //
- int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
- (int)process.GetID() };
-
- struct kinfo_proc processInfo;
- size_t bufsize = sizeof(processInfo);
- if ((sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo,
- &bufsize, NULL, 0) == 0) && (bufsize > 0))
- {
- if (processInfo.kp_proc.p_flag & P_LP64)
- m_is_64_bit = true;
- }
// TODO implement architecture selection and abstraction.
#if 0
-#if defined (__i386__) || defined (__x86_64__)
+#if defined(__i386__) || defined(__x86_64__)
if (m_is_64_bit)
DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64);
else
DNBArchProtocol::SetArchitecture(CPU_TYPE_I386);
-#elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
+#elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
if (m_is_64_bit)
DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64);
else
DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM);
#endif
#endif
+ }
+
+ if (m_threads.empty() || update) {
+ thread_array_t thread_list = nullptr;
+ mach_msg_type_number_t thread_list_count = 0;
+ task_t task = process.GetTask();
+
+ Error error;
+ auto mach_err = ::task_threads(task, &thread_list, &thread_list_count);
+ error.SetError(mach_err, eErrorTypeMachKernel);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("::task_threads(task = 0x%4.4x, thread_list => %p, "
+ "thread_list_count => %u) failed: %u (%s)",
+ task, thread_list, thread_list_count, error.GetError(),
+ error.AsCString());
+ return 0;
}
-
- if (m_threads.empty() || update)
- {
- thread_array_t thread_list = nullptr;
- mach_msg_type_number_t thread_list_count = 0;
- task_t task = process.GetTask();
-
- Error error;
- auto mach_err = ::task_threads(task, &thread_list, &thread_list_count);
- error.SetError(mach_err, eErrorTypeMachKernel);
- if (error.Fail())
- {
- if (log)
- log->Printf("::task_threads(task = 0x%4.4x, thread_list => %p, "
- "thread_list_count => %u) failed: %u (%s)", task,
- thread_list, thread_list_count, error.GetError(),
- error.AsCString());
- return 0;
- }
- if (thread_list_count > 0)
- {
- collection currThreads;
- size_t idx;
- // Iterator through the current thread list and see which threads
- // we already have in our list (keep them), which ones we don't
- // (add them), and which ones are not around anymore (remove them).
- for (idx = 0; idx < thread_list_count; ++idx)
- {
- // Get the Mach thread port.
- const ::thread_t mach_port_num = thread_list[idx];
-
- // Get the unique thread id for the mach port number.
- uint64_t unique_thread_id =
- NativeThreadDarwin::
- GetGloballyUniqueThreadIDForMachPortID(mach_port_num);
-
- // Retrieve the thread if it exists.
- auto thread_sp = GetThreadByID(unique_thread_id);
- if (thread_sp)
- {
- // We are already tracking it. Keep the existing native
- // thread instance.
- currThreads.push_back(thread_sp);
- }
- else
- {
- // We don't have a native thread instance for this thread.
- // Create it now.
- thread_sp.reset(new NativeThreadDarwin(&process,
- m_is_64_bit,
- unique_thread_id,
- mach_port_num));
-
- // Add the new thread regardless of its is user ready state.
- // Make sure the thread is ready to be displayed and shown
- // to users before we add this thread to our list...
- if (thread_sp->IsUserReady())
- {
- if (new_threads)
- new_threads->push_back(thread_sp);
-
- currThreads.push_back(thread_sp);
- }
- }
- }
+ if (thread_list_count > 0) {
+ collection currThreads;
+ size_t idx;
+ // Iterator through the current thread list and see which threads
+ // we already have in our list (keep them), which ones we don't
+ // (add them), and which ones are not around anymore (remove them).
+ for (idx = 0; idx < thread_list_count; ++idx) {
+ // Get the Mach thread port.
+ const ::thread_t mach_port_num = thread_list[idx];
+
+ // Get the unique thread id for the mach port number.
+ uint64_t unique_thread_id =
+ NativeThreadDarwin::GetGloballyUniqueThreadIDForMachPortID(
+ mach_port_num);
+
+ // Retrieve the thread if it exists.
+ auto thread_sp = GetThreadByID(unique_thread_id);
+ if (thread_sp) {
+ // We are already tracking it. Keep the existing native
+ // thread instance.
+ currThreads.push_back(thread_sp);
+ } else {
+ // We don't have a native thread instance for this thread.
+ // Create it now.
+ thread_sp.reset(new NativeThreadDarwin(
+ &process, m_is_64_bit, unique_thread_id, mach_port_num));
+
+ // Add the new thread regardless of its is user ready state.
+ // Make sure the thread is ready to be displayed and shown
+ // to users before we add this thread to our list...
+ if (thread_sp->IsUserReady()) {
+ if (new_threads)
+ new_threads->push_back(thread_sp);
+
+ currThreads.push_back(thread_sp);
+ }
+ }
+ }
- m_threads.swap(currThreads);
- m_current_thread.reset();
+ m_threads.swap(currThreads);
+ m_current_thread.reset();
- // Free the vm memory given to us by ::task_threads()
- vm_size_t thread_list_size = (vm_size_t) (thread_list_count *
- sizeof (::thread_t));
- ::vm_deallocate(::mach_task_self(),
- (vm_address_t)thread_list,
- thread_list_size);
- }
+ // Free the vm memory given to us by ::task_threads()
+ vm_size_t thread_list_size =
+ (vm_size_t)(thread_list_count * sizeof(::thread_t));
+ ::vm_deallocate(::mach_task_self(), (vm_address_t)thread_list,
+ thread_list_size);
}
- return static_cast<uint32_t>(m_threads.size());
+ }
+ return static_cast<uint32_t>(m_threads.size());
}
// TODO implement
@@ -470,37 +435,31 @@ NativeThreadListDarwin::CurrentThread (MachThreadSP& thread_sp)
#endif
-void
-NativeThreadListDarwin::Dump(Stream &stream) const
-{
- bool first = true;
-
- std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- for (auto thread_sp : m_threads)
- {
- if (thread_sp)
- {
- // Handle newlines between thread entries.
- if (first)
- first = false;
- else
- stream.PutChar('\n');
- thread_sp->Dump(stream);
- }
+void NativeThreadListDarwin::Dump(Stream &stream) const {
+ bool first = true;
+
+ std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
+ for (auto thread_sp : m_threads) {
+ if (thread_sp) {
+ // Handle newlines between thread entries.
+ if (first)
+ first = false;
+ else
+ stream.PutChar('\n');
+ thread_sp->Dump(stream);
}
+ }
}
-void
-NativeThreadListDarwin::ProcessWillResume(NativeProcessDarwin &process,
- const ResumeActionList &thread_actions)
-{
- std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
+void NativeThreadListDarwin::ProcessWillResume(
+ NativeProcessDarwin &process, const ResumeActionList &thread_actions) {
+ std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- // Update our thread list, because sometimes libdispatch or the kernel
- // will spawn threads while a task is suspended.
- NativeThreadListDarwin::collection new_threads;
+ // Update our thread list, because sometimes libdispatch or the kernel
+ // will spawn threads while a task is suspended.
+ NativeThreadListDarwin::collection new_threads;
- // TODO implement this.
+// TODO implement this.
#if 0
// First figure out if we were planning on running only one thread, and if
// so, force that thread to resume.
@@ -526,7 +485,7 @@ NativeThreadListDarwin::ProcessWillResume(NativeProcessDarwin &process,
run_one_thread = false;
#endif
- UpdateThreadList(process, true, &new_threads);
+ UpdateThreadList(process, true, &new_threads);
#if 0
DNBThreadResumeAction resume_new_threads = { -1U, eStateRunning, 0, INVALID_NUB_ADDRESS };
@@ -576,20 +535,17 @@ NativeThreadListDarwin::ProcessWillResume(NativeProcessDarwin &process,
#endif
}
-uint32_t
-NativeThreadListDarwin::ProcessDidStop(NativeProcessDarwin &process)
-{
- std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
+uint32_t NativeThreadListDarwin::ProcessDidStop(NativeProcessDarwin &process) {
+ std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- // Update our thread list.
- UpdateThreadList(process, true);
+ // Update our thread list.
+ UpdateThreadList(process, true);
- for (auto thread_sp : m_threads)
- {
- if (thread_sp)
- thread_sp->ThreadDidStop();
- }
- return (uint32_t)m_threads.size();
+ for (auto thread_sp : m_threads) {
+ if (thread_sp)
+ thread_sp->ThreadDidStop();
+ }
+ return (uint32_t)m_threads.size();
}
//----------------------------------------------------------------------
@@ -603,16 +559,13 @@ NativeThreadListDarwin::ProcessDidStop(NativeProcessDarwin &process)
// true if we should stop and notify our clients
// false if we should resume our child process and skip notification
//----------------------------------------------------------------------
-bool
-NativeThreadListDarwin::ShouldStop(bool &step_more)
-{
- std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- for (auto thread_sp : m_threads)
- {
- if (thread_sp && thread_sp->ShouldStop(step_more))
- return true;
- }
- return false;
+bool NativeThreadListDarwin::ShouldStop(bool &step_more) {
+ std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
+ for (auto thread_sp : m_threads) {
+ if (thread_sp && thread_sp->ShouldStop(step_more))
+ return true;
+ }
+ return false;
}
// Implement.
diff --git a/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.h b/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.h
index 588013043e1..2b194bcc153 100644
--- a/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.h
+++ b/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.h
@@ -1,4 +1,5 @@
-//===-- NativeThreadListDarwin.h --------------------------------------*- C++ -*-===//
+//===-- NativeThreadListDarwin.h --------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -34,19 +35,16 @@ class NativeProcessDarwin;
class NativeThreadDarwin;
using NativeThreadDarwinSP = std::shared_ptr<NativeThreadDarwin>;
-class NativeThreadListDarwin
-{
+class NativeThreadListDarwin {
public:
- NativeThreadListDarwin();
- ~NativeThreadListDarwin();
+ NativeThreadListDarwin();
+ ~NativeThreadListDarwin();
- void
- Clear();
+ void Clear();
- void
- Dump(Stream &stream) const;
+ void Dump(Stream &stream) const;
- // These methods will be accessed directly from NativeThreadDarwin
+// These methods will be accessed directly from NativeThreadDarwin
#if 0
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 *reg_value) const;
@@ -56,30 +54,25 @@ public:
bool RestoreRegisterState (nub_thread_t tid, uint32_t save_id);
#endif
- const char *
- GetThreadInfo(lldb::tid_t tid) const;
+ const char *GetThreadInfo(lldb::tid_t tid) const;
- void
- ProcessWillResume(NativeProcessDarwin &process,
- const ResumeActionList &thread_actions);
+ void ProcessWillResume(NativeProcessDarwin &process,
+ const ResumeActionList &thread_actions);
- uint32_t
- ProcessDidStop(NativeProcessDarwin &process);
+ uint32_t ProcessDidStop(NativeProcessDarwin &process);
- bool
- NotifyException(MachException::Data& exc);
+ bool NotifyException(MachException::Data &exc);
- bool
- ShouldStop(bool &step_more);
+ bool ShouldStop(bool &step_more);
- // These methods will be accessed directly from NativeThreadDarwin
+// These methods will be accessed directly from NativeThreadDarwin
#if 0
const char * GetName (nub_thread_t tid);
nub_state_t GetState (nub_thread_t tid);
nub_thread_t SetCurrentThread (nub_thread_t tid);
#endif
- // TODO: figure out if we need to add this to NativeThreadDarwin yet.
+// TODO: figure out if we need to add this to NativeThreadDarwin yet.
#if 0
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);
@@ -87,76 +80,60 @@ public:
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);
#endif
- // These methods will be accessed directly from NativeThreadDarwin
+// These methods will be accessed directly from NativeThreadDarwin
#if 0
bool GetThreadStoppedReason (nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const;
void DumpThreadStoppedReason (nub_thread_t tid) const;
bool GetIdentifierInfo (nub_thread_t tid, thread_identifier_info_data_t *ident_info);
#endif
- size_t
- GetNumberOfThreads() const;
+ size_t GetNumberOfThreads() const;
- lldb::tid_t
- ThreadIDAtIndex(size_t idx) const;
+ lldb::tid_t ThreadIDAtIndex(size_t idx) const;
- lldb::tid_t
- GetCurrentThreadID();
+ lldb::tid_t GetCurrentThreadID();
- NativeThreadDarwinSP
- GetCurrentThread();
+ NativeThreadDarwinSP GetCurrentThread();
- void
- NotifyBreakpointChanged(const NativeBreakpointDarwin *bp);
+ void NotifyBreakpointChanged(const NativeBreakpointDarwin *bp);
- uint32_t
- EnableHardwareBreakpoint(const NativeBreakpointDarwin *bp) const;
+ uint32_t EnableHardwareBreakpoint(const NativeBreakpointDarwin *bp) const;
- bool
- DisableHardwareBreakpoint(const NativeBreakpointDarwin *bp) const;
+ bool DisableHardwareBreakpoint(const NativeBreakpointDarwin *bp) const;
- uint32_t
- EnableHardwareWatchpoint(const NativeBreakpointDarwin *wp) const;
+ uint32_t EnableHardwareWatchpoint(const NativeBreakpointDarwin *wp) const;
- bool
- DisableHardwareWatchpoint(const NativeBreakpointDarwin *wp) const;
+ bool DisableHardwareWatchpoint(const NativeBreakpointDarwin *wp) const;
- uint32_t
- GetNumberOfSupportedHardwareWatchpoints() const;
+ uint32_t GetNumberOfSupportedHardwareWatchpoints() const;
- size_t
- GetThreadIndexForThreadStoppedWithSignal(const int signo) const;
+ size_t GetThreadIndexForThreadStoppedWithSignal(const int signo) const;
- NativeThreadDarwinSP
- GetThreadByID(lldb::tid_t tid) const;
+ NativeThreadDarwinSP GetThreadByID(lldb::tid_t tid) const;
- NativeThreadDarwinSP
- GetThreadByMachPortNumber(::thread_t mach_port_number) const;
+ NativeThreadDarwinSP
+ GetThreadByMachPortNumber(::thread_t mach_port_number) const;
- lldb::tid_t
- GetThreadIDByMachPortNumber(::thread_t mach_port_number) const;
+ lldb::tid_t GetThreadIDByMachPortNumber(::thread_t mach_port_number) const;
- thread_t
- GetMachPortNumberByThreadID(lldb::tid_t globally_unique_id) const;
+ thread_t GetMachPortNumberByThreadID(lldb::tid_t globally_unique_id) const;
protected:
- typedef std::vector<NativeThreadDarwinSP> collection;
- typedef collection::iterator iterator;
- typedef collection::const_iterator const_iterator;
-
- // Consider having this return an lldb_private::Error.
- uint32_t
- UpdateThreadList (NativeProcessDarwin &process, bool update,
- collection *num_threads = nullptr);
-
- collection m_threads;
- mutable std::recursive_mutex m_threads_mutex;
- NativeThreadDarwinSP m_current_thread;
- bool m_is_64_bit;
+ typedef std::vector<NativeThreadDarwinSP> collection;
+ typedef collection::iterator iterator;
+ typedef collection::const_iterator const_iterator;
+
+ // Consider having this return an lldb_private::Error.
+ uint32_t UpdateThreadList(NativeProcessDarwin &process, bool update,
+ collection *num_threads = nullptr);
+
+ collection m_threads;
+ mutable std::recursive_mutex m_threads_mutex;
+ NativeThreadDarwinSP m_current_thread;
+ bool m_is_64_bit;
};
} // namespace process_darwin
} // namespace lldb_private
#endif // #ifndef __NativeThreadListDarwin_h__
-
OpenPOWER on IntegriCloud