| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| from __future__ import print_function | ||
|
|
||
| # lldb test suite imports | ||
| from lldbsuite.test.decorators import * | ||
| from lldbsuite.test.lldbtest import TestBase | ||
|
|
||
| # gdb-remote-specific imports | ||
| import lldbgdbserverutils | ||
| from gdbremote_testcase import GdbRemoteTestCaseBase | ||
|
|
||
|
|
||
| class TestGdbRemoteHostInfo(GdbRemoteTestCaseBase): | ||
|
|
||
| mydir = TestBase.compute_mydir(__file__) | ||
|
|
||
| KNOWN_HOST_INFO_KEYS = set([ | ||
| "cputype", | ||
| "cpusubtype", | ||
| "distribution_id", | ||
| "endian", | ||
| "hostname", | ||
| "ostype", | ||
| "os_build", | ||
| "os_kernel", | ||
| "os_version", | ||
| "ptrsize", | ||
| "triple", | ||
| "vendor", | ||
| "watchpoint_exceptions_received" | ||
| ]) | ||
|
|
||
| DARWIN_REQUIRED_HOST_INFO_KEYS = set([ | ||
| "cputype", | ||
| "cpusubtype", | ||
| "endian", | ||
| "ostype", | ||
| "ptrsize", | ||
| "vendor", | ||
| "watchpoint_exceptions_received" | ||
| ]) | ||
|
|
||
| def add_host_info_collection_packets(self): | ||
| self.test_sequence.add_log_lines( | ||
| ["read packet: $qHostInfo#9b", | ||
| {"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$", | ||
| "capture": {1: "host_info_raw"}}], | ||
| True) | ||
|
|
||
| def parse_host_info_response(self, context): | ||
| # Ensure we have a host info response. | ||
| self.assertIsNotNone(context) | ||
| host_info_raw = context.get("host_info_raw") | ||
| self.assertIsNotNone(host_info_raw) | ||
|
|
||
| # Pull out key:value; pairs. | ||
| host_info_dict = {match.group(1): match.group(2) | ||
| for match in re.finditer(r"([^:]+):([^;]+);", | ||
| host_info_raw)} | ||
|
|
||
| import pprint | ||
| print("\nqHostInfo response:") | ||
| pprint.pprint(host_info_dict) | ||
|
|
||
| # Validate keys are known. | ||
| for (key, val) in list(host_info_dict.items()): | ||
| self.assertTrue(key in self.KNOWN_HOST_INFO_KEYS, | ||
| "unknown qHostInfo key: " + key) | ||
| self.assertIsNotNone(val) | ||
|
|
||
| # Return the key:val pairs. | ||
| return host_info_dict | ||
|
|
||
| def get_qHostInfo_response(self): | ||
| # Launch the debug monitor stub, attaching to the inferior. | ||
| server = self.connect_to_debug_monitor() | ||
| self.assertIsNotNone(server) | ||
| self.add_no_ack_remote_stream() | ||
|
|
||
| # Request qHostInfo and get response | ||
| self.add_host_info_collection_packets() | ||
| context = self.expect_gdbremote_sequence() | ||
| self.assertIsNotNone(context) | ||
|
|
||
| # Parse qHostInfo response. | ||
| host_info = self.parse_host_info_response(context) | ||
| self.assertIsNotNone(host_info) | ||
| self.assertGreater(len(host_info), 0, "qHostInfo should have returned " | ||
| "at least one key:val pair.") | ||
| return host_info | ||
|
|
||
| def validate_darwin_minimum_host_info_keys(self, host_info_dict): | ||
| self.assertIsNotNone(host_info_dict) | ||
| missing_keys = [key for key in self.DARWIN_REQUIRED_HOST_INFO_KEYS | ||
| if key not in host_info_dict] | ||
| self.assertEquals(0, len(missing_keys), | ||
| "qHostInfo is missing the following required " | ||
| "keys: " + str(missing_keys)) | ||
|
|
||
| @debugserver_test | ||
| def test_qHostInfo_returns_at_least_one_key_val_pair_debugserver(self): | ||
| self.init_debugserver_test() | ||
| self.build() | ||
| self.get_qHostInfo_response() | ||
|
|
||
| @llgs_test | ||
| def test_qHostInfo_returns_at_least_one_key_val_pair_llgs(self): | ||
| self.init_llgs_test() | ||
| self.build() | ||
| self.get_qHostInfo_response() | ||
|
|
||
| @skipUnlessDarwin | ||
| @debugserver_test | ||
| def test_qHostInfo_contains_darwin_required_keys_debugserver(self): | ||
| self.init_debugserver_test() | ||
| self.build() | ||
| host_info_dict = self.get_qHostInfo_response() | ||
| self.validate_darwin_minimum_host_info_keys(host_info_dict) | ||
|
|
||
| @skipUnlessDarwin | ||
| @llgs_test | ||
| def test_qHostInfo_contains_darwin_required_keys_llgs(self): | ||
| self.init_llgs_test() | ||
| self.build() | ||
| host_info_dict = self.get_qHostInfo_response() | ||
| self.validate_darwin_minimum_host_info_keys(host_info_dict) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| //===-- CFBundle.cpp --------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Created by Greg Clayton on 1/16/08. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "CFBundle.h" | ||
| #include "CFString.h" | ||
|
|
||
| //---------------------------------------------------------------------- | ||
| // CFBundle constructor | ||
| //---------------------------------------------------------------------- | ||
| 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 copy constructor | ||
| //---------------------------------------------------------------------- | ||
| CFBundle& | ||
| CFBundle::operator=(const CFBundle& rhs) | ||
| { | ||
| *this = rhs; | ||
| return *this; | ||
| } | ||
|
|
||
| //---------------------------------------------------------------------- | ||
| // Destructor | ||
| //---------------------------------------------------------------------- | ||
| 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())); | ||
| } | ||
| } | ||
| return get() != NULL; | ||
| } | ||
|
|
||
| CFStringRef | ||
| CFBundle::GetIdentifier () const | ||
| { | ||
| CFBundleRef bundle = get(); | ||
| if (bundle != NULL) | ||
| return ::CFBundleGetIdentifier (bundle); | ||
| return NULL; | ||
| } | ||
|
|
||
|
|
||
| CFURLRef | ||
| CFBundle::CopyExecutableURL () const | ||
| { | ||
| CFBundleRef bundle = get(); | ||
| if (bundle != NULL) | ||
| return CFBundleCopyExecutableURL(bundle); | ||
| return NULL; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===-- CFBundle.h ----------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Created by Greg Clayton on 1/16/08. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef __CFBundle_h__ | ||
| #define __CFBundle_h__ | ||
|
|
||
| #include "CFUtils.h" | ||
|
|
||
| class CFBundle : public CFReleaser<CFBundleRef> | ||
| { | ||
| public: | ||
| //------------------------------------------------------------------ | ||
| // Constructors and Destructors | ||
| //------------------------------------------------------------------ | ||
| CFBundle(const char *path = NULL); | ||
| CFBundle(const CFBundle& rhs); | ||
| CFBundle& operator=(const CFBundle& rhs); | ||
| virtual | ||
| ~CFBundle(); | ||
| bool | ||
| SetPath (const char *path); | ||
|
|
||
| CFStringRef | ||
| GetIdentifier () const; | ||
|
|
||
| CFURLRef | ||
| CopyExecutableURL () const; | ||
|
|
||
| protected: | ||
| CFReleaser<CFURLRef> m_bundle_url; | ||
| }; | ||
|
|
||
| #endif // #ifndef __CFBundle_h__ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,201 @@ | ||
| //===-- CFString.cpp --------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Created by Greg Clayton on 1/16/08. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "CFString.h" | ||
| #include <string> | ||
| #include <glob.h> | ||
|
|
||
| //---------------------------------------------------------------------- | ||
| // CFString constructor | ||
| //---------------------------------------------------------------------- | ||
| CFString::CFString(CFStringRef s) : | ||
| CFReleaser<CFStringRef> (s) | ||
| { | ||
| } | ||
|
|
||
| //---------------------------------------------------------------------- | ||
| // CFString copy constructor | ||
| //---------------------------------------------------------------------- | ||
| 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 (const char *cstr, CFStringEncoding cstr_encoding) : | ||
| CFReleaser<CFStringRef> () | ||
| { | ||
| if (cstr && cstr[0]) | ||
| { | ||
| reset(::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); | ||
| } | ||
| } | ||
|
|
||
| //---------------------------------------------------------------------- | ||
| // Destructor | ||
| //---------------------------------------------------------------------- | ||
| CFString::~CFString() | ||
| { | ||
| } | ||
|
|
||
| const char * | ||
| CFString::GetFileSystemRepresentation(std::string& s) | ||
| { | ||
| return CFString::FileSystemRepresentation(get(), s); | ||
| } | ||
|
|
||
| CFStringRef | ||
| CFString::SetFileSystemRepresentation (const char *path) | ||
| { | ||
| CFStringRef new_value = NULL; | ||
| if (path && path[0]) | ||
| new_value = ::CFStringCreateWithFileSystemRepresentation (kCFAllocatorDefault, path); | ||
| reset(new_value); | ||
| return get(); | ||
| } | ||
|
|
||
|
|
||
| CFStringRef | ||
| CFString::SetFileSystemRepresentationFromCFType (CFTypeRef cf_type) | ||
| { | ||
| CFStringRef new_value = NULL; | ||
| if (cf_type != NULL) | ||
| { | ||
| CFTypeID cf_type_id = ::CFGetTypeID(cf_type); | ||
|
|
||
| if (cf_type_id == ::CFStringGetTypeID()) | ||
| { | ||
| // Retain since we are using the existing object | ||
| new_value = (CFStringRef)::CFRetain(cf_type); | ||
| } | ||
| else if (cf_type_id == ::CFURLGetTypeID()) | ||
| { | ||
| new_value = ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); | ||
| } | ||
| } | ||
| 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(); | ||
| } | ||
|
|
||
| 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(); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
||
| // Static function that puts a copy of the file system representation 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::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; | ||
| } | ||
|
|
||
|
|
||
| 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(); | ||
|
|
||
| return expanded_path.c_str(); | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===-- CFString.h ----------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Created by Greg Clayton on 1/16/08. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef __CFString_h__ | ||
| #define __CFString_h__ | ||
|
|
||
| #include "CFUtils.h" | ||
| #include <iosfwd> | ||
|
|
||
| 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 (); | ||
|
|
||
| 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__ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| //===-- CFUtils.h -----------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Created by Greg Clayton on 3/5/07. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef __CFUtils_h__ | ||
| #define __CFUtils_h__ | ||
|
|
||
| #include <CoreFoundation/CoreFoundation.h> | ||
|
|
||
| #ifdef __cplusplus | ||
|
|
||
| //---------------------------------------------------------------------- | ||
| // Templatized CF helper class that can own any CF pointer and will | ||
| // call CFRelease() on any valid pointer it owns unless that pointer is | ||
| // explicitly released using the release() member function. | ||
| //---------------------------------------------------------------------- | ||
| template <class T> | ||
| class CFReleaser | ||
| { | ||
| public: | ||
| // Type names for the avlue | ||
| typedef T element_type; | ||
|
|
||
| // Constructors and destructors | ||
| CFReleaser(T ptr = NULL) : _ptr(ptr) { } | ||
| CFReleaser(const CFReleaser& copy) : _ptr(copy.get()) | ||
| { | ||
| if (get()) | ||
| ::CFRetain(get()); | ||
| } | ||
| virtual ~CFReleaser() { reset(); } | ||
|
|
||
| // Assignments | ||
| CFReleaser& operator= (const CFReleaser<T>& copy) | ||
| { | ||
| if (copy != *this) | ||
| { | ||
| // Replace our owned pointer with the new one | ||
| reset(copy.get()); | ||
| // Retain the current pointer that we own | ||
| if (get()) | ||
| ::CFRetain(get()); | ||
| } | ||
| } | ||
| // Get the address of the contained type | ||
| T * ptr_address() { return &_ptr; } | ||
|
|
||
| // Access the pointer itself | ||
| const T get() const { return _ptr; } | ||
| T get() { return _ptr; } | ||
|
|
||
| // Set a new value for the pointer and CFRelease our old | ||
| // value if we had a valid one. | ||
| void reset(T ptr = NULL) | ||
| { | ||
| if (ptr != _ptr) | ||
| { | ||
| if (_ptr != NULL) | ||
| ::CFRelease(_ptr); | ||
| _ptr = ptr; | ||
| } | ||
| } | ||
|
|
||
| // Release ownership without calling CFRelease | ||
| T release() { T tmp = _ptr; _ptr = NULL; return tmp; } | ||
| private: | ||
| element_type _ptr; | ||
| }; | ||
|
|
||
| #endif // #ifdef __cplusplus | ||
| #endif // #ifndef __CFUtils_h__ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| //===-- DarwinProcessLauncher.h ---------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef DarwinProcessLauncher_h | ||
| #define DarwinProcessLauncher_h | ||
|
|
||
| // C headers | ||
| #include <mach/machine.h> | ||
| #include <sys/types.h> | ||
|
|
||
| // C++ headers | ||
| #include <functional> | ||
|
|
||
| // LLDB headers | ||
| #include "lldb/lldb-enumerations.h" | ||
| #include "lldb/lldb-forward.h" | ||
|
|
||
| #include "LaunchFlavor.h" | ||
|
|
||
| namespace lldb_private | ||
| { | ||
| namespace darwin_process_launcher | ||
| { | ||
| // ============================================================================= | ||
| /// Launches a process for debugging. | ||
| /// | ||
| /// @param[inout] launch_info | ||
| /// Specifies details about the process to launch (e.g. path, architecture, | ||
| /// etc.). On output, includes the launched ProcessID (pid). | ||
| /// | ||
| /// @param[out] pty_master_fd | ||
| /// Returns the master side of the pseudo-terminal used to communicate | ||
| /// with stdin/stdout from the launched process. May be nullptr. | ||
| /// | ||
| /// @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); | ||
|
|
||
| } // darwin_process_launcher | ||
| } // lldb_private | ||
|
|
||
| #endif /* DarwinProcessLauncher_h */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| //===-- LaunchFlavor.h ---------------------------------------- -*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LaunchFlavor_h | ||
| #define LaunchFlavor_h | ||
|
|
||
| namespace lldb_private { | ||
| namespace process_darwin { | ||
|
|
||
| enum class LaunchFlavor | ||
| { | ||
| Default = 0, | ||
| PosixSpawn = 1, | ||
| ForkExec = 2, | ||
| #ifdef WITH_SPRINGBOARD | ||
| SpringBoard = 3, | ||
| #endif | ||
| #ifdef WITH_BKS | ||
| BKS = 4, | ||
| #endif | ||
| #ifdef WITH_FBS | ||
| FBS = 5 | ||
| #endif | ||
| }; | ||
|
|
||
| }} // namespaces | ||
|
|
||
| #endif /* LaunchFlavor_h */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,163 @@ | ||
| //===-- MachException.h -----------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Created by Greg Clayton on 6/18/07. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
|
|
||
| #ifndef __MachException_h__ | ||
| #define __MachException_h__ | ||
|
|
||
| #include <mach/mach.h> | ||
| #include <vector> | ||
|
|
||
| #include "lldb/lldb-private-forward.h" | ||
| #include "lldb/lldb-types.h" | ||
| #include "lldb/Host/Debug.h" | ||
|
|
||
| namespace lldb_private | ||
| { | ||
| namespace process_darwin | ||
| { | ||
|
|
||
| typedef union MachMessageTag | ||
| { | ||
| mach_msg_header_t hdr; | ||
| char data[1024]; | ||
| } MachMessage; | ||
|
|
||
|
|
||
| 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); | ||
| }; | ||
|
|
||
| } // namespace process_darwin | ||
| } // namespace lldb_private | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,324 @@ | ||
| //===-- NativeThreadDarwin.cpp -------------------------------- -*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "NativeThreadDarwin.h" | ||
|
|
||
| // C includes | ||
| #include <libproc.h> | ||
|
|
||
| // LLDB includes | ||
| #include "lldb/Core/Stream.h" | ||
|
|
||
| #include "NativeProcessDarwin.h" | ||
|
|
||
| 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; | ||
| } | ||
|
|
||
| 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; | ||
| } | ||
|
|
||
| std::string | ||
| NativeThreadDarwin::GetName() | ||
| { | ||
| std::string 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)); | ||
|
|
||
| if (len && m_proc_threadinfo.pth_name[0]) | ||
| name = m_proc_threadinfo.pth_name; | ||
| } | ||
| return name; | ||
| } | ||
|
|
||
| lldb::StateType | ||
| NativeThreadDarwin::GetState() | ||
| { | ||
| // TODO implement | ||
| return eStateInvalid; | ||
| } | ||
|
|
||
| bool | ||
| NativeThreadDarwin::GetStopReason(ThreadStopInfo &stop_info, | ||
| std::string& description) | ||
| { | ||
| // TODO implement | ||
| return false; | ||
| } | ||
|
|
||
| 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::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. | ||
| #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, | ||
| m_seq_id, | ||
| m_unique_id, | ||
| GetPC(INVALID_NUB_ADDRESS), | ||
| GetSP(INVALID_NUB_ADDRESS), | ||
| m_basic_info.user_time.seconds, m_basic_info.user_time.microseconds, | ||
| m_basic_info.system_time.seconds, m_basic_info.system_time.microseconds, | ||
| m_basic_info.cpu_usage, | ||
| m_basic_info.policy, | ||
| m_basic_info.run_state, | ||
| thread_run_state, | ||
| m_basic_info.flags, | ||
| m_basic_info.suspend_count, m_suspend_count, | ||
| 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); | ||
| #endif | ||
| } | ||
|
|
||
| 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. | ||
| // See also MachThread::GetStopException(). | ||
| bool handled = m_arch_ap->NotifyException(exc); | ||
|
|
||
| if (m_stop_exception.IsValid()) | ||
| { | ||
| // We may have more than one exception for a thread, but we need to | ||
| // only remember the one that we will say is the reason we stopped. | ||
| // We may have been single stepping and also gotten a signal exception, | ||
| // so just remember the most pertinent one. | ||
| if (m_stop_exception.IsBreakpoint()) | ||
| m_stop_exception = exc; | ||
| } | ||
| else | ||
| { | ||
| m_stop_exception = exc; | ||
| } | ||
|
|
||
| return handled; | ||
| #else | ||
| // Pretend we handled it. | ||
| return true; | ||
| #endif | ||
| } | ||
|
|
||
| bool | ||
| NativeThreadDarwin::ShouldStop(bool &step_more) const | ||
| { | ||
| // TODO: implement this | ||
| #if 0 | ||
| // See if this thread is at a breakpoint? | ||
| DNBBreakpoint *bp = CurrentBreakpoint(); | ||
|
|
||
| if (bp) | ||
| { | ||
| // This thread is sitting at a breakpoint, ask the breakpoint | ||
| // if we should be stopping here. | ||
| return true; | ||
| } | ||
| else | ||
| { | ||
| if (m_arch_ap->StepNotComplete()) | ||
| { | ||
| step_more = true; | ||
| return false; | ||
| } | ||
| // The thread state is used to let us know what the thread was | ||
| // trying to do. MachThread::ThreadWillResume() will set the | ||
| // thread state to various values depending if the thread was | ||
| // the current thread and if it was to be single stepped, or | ||
| // resumed. | ||
| if (GetState() == eStateRunning) | ||
| { | ||
| // If our state is running, then we should continue as we are in | ||
| // the process of stepping over a breakpoint. | ||
| return false; | ||
| } | ||
| else | ||
| { | ||
| // Stop if we have any kind of valid exception for this | ||
| // thread. | ||
| if (GetStopException().IsValid()) | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| #else | ||
| return false; | ||
| #endif | ||
| } | ||
|
|
||
| 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 | ||
| // after running. | ||
|
|
||
| // The thread state and breakpoint will still have the same values | ||
| // as they had prior to resuming the thread, so it makes it easy to check | ||
| // if we were trying to step a thread, or we tried to resume while being | ||
| // at a breakpoint. | ||
|
|
||
| // When this method gets called, the process state is still in the | ||
| // state it was in while running so we can act accordingly. | ||
| m_arch_ap->ThreadDidStop(); | ||
|
|
||
|
|
||
| // We may have suspended this thread so the primary thread could step | ||
| // without worrying about race conditions, so lets restore our suspend | ||
| // count. | ||
| RestoreSuspendCountAfterStop(); | ||
|
|
||
| // Update the basic information for a thread | ||
| MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info); | ||
|
|
||
| if (m_basic_info.suspend_count > 0) | ||
| SetState(eStateSuspended); | ||
| else | ||
| SetState(eStateStopped); | ||
| #endif | ||
| } | ||
|
|
||
| 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; | ||
| } | ||
|
|
||
| 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(); | ||
|
|
||
| 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()); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,216 @@ | ||
| //===-- NativeThreadDarwin.h ---------------------------------- -*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef NativeThreadDarwin_H | ||
| #define NativeThreadDarwin_H | ||
|
|
||
| // C includes | ||
| #include <mach/mach_types.h> | ||
| #include <sched.h> | ||
| #include <sys/proc_info.h> | ||
|
|
||
| // C++ includes | ||
| #include <map> | ||
| #include <memory> | ||
| #include <string> | ||
|
|
||
| // LLDB includes | ||
| #include "lldb/lldb-private-forward.h" | ||
| #include "lldb/Host/common/NativeThreadProtocol.h" | ||
|
|
||
| #include "MachException.h" | ||
|
|
||
| namespace lldb_private { | ||
| namespace process_darwin { | ||
|
|
||
| class NativeProcessDarwin; | ||
| using NativeProcessDarwinSP = std::shared_ptr<NativeProcessDarwin>; | ||
|
|
||
| class NativeThreadListDarwin; | ||
|
|
||
| class NativeThreadDarwin : public NativeThreadProtocol | ||
| { | ||
| friend class NativeProcessDarwin; | ||
| friend class NativeThreadListDarwin; | ||
|
|
||
| public: | ||
|
|
||
| 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); | ||
|
|
||
| // ----------------------------------------------------------------- | ||
| // NativeThreadProtocol Interface | ||
| // ----------------------------------------------------------------- | ||
| std::string | ||
| GetName() override; | ||
|
|
||
| lldb::StateType | ||
| GetState () override; | ||
|
|
||
| bool | ||
| GetStopReason(ThreadStopInfo &stop_info, | ||
| std::string& description) override; | ||
|
|
||
| NativeRegisterContextSP | ||
| GetRegisterContext() override; | ||
|
|
||
| Error | ||
| SetWatchpoint(lldb::addr_t addr, size_t size, | ||
| uint32_t watch_flags, bool hardware) override; | ||
|
|
||
| Error | ||
| RemoveWatchpoint(lldb::addr_t addr) override; | ||
|
|
||
| // ----------------------------------------------------------------- | ||
| // New methods that are fine for others to call. | ||
| // ----------------------------------------------------------------- | ||
| void | ||
| Dump(Stream &stream) const; | ||
|
|
||
| private: | ||
| // ----------------------------------------------------------------- | ||
| // 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); | ||
|
|
||
| /// 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 | ||
| ShouldStop(bool &step_more) const; | ||
|
|
||
| void | ||
| ThreadDidStop(); | ||
|
|
||
| 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); | ||
|
|
||
| const struct thread_basic_info * | ||
| GetBasicInfo() const; | ||
|
|
||
| static bool | ||
| GetBasicInfo(::thread_t thread, struct thread_basic_info *basicInfoPtr); | ||
|
|
||
| bool | ||
| IsUserReady() const; | ||
|
|
||
| void | ||
| SetStoppedByExec (); | ||
|
|
||
| void | ||
| SetStoppedByBreakpoint (); | ||
|
|
||
| void | ||
| SetStoppedByWatchpoint (uint32_t wp_index); | ||
|
|
||
| bool | ||
| IsStoppedAtBreakpoint (); | ||
|
|
||
| bool | ||
| IsStoppedAtWatchpoint (); | ||
|
|
||
| void | ||
| SetStoppedByTrace (); | ||
|
|
||
| void | ||
| SetStoppedWithNoReason (); | ||
|
|
||
| void | ||
| SetExited (); | ||
|
|
||
| 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; | ||
| } | ||
|
|
||
| static bool | ||
| MachPortNumberIsValid(::thread_t thread); | ||
|
|
||
| // --------------------------------------------------------------------- | ||
| // Private interface | ||
| // --------------------------------------------------------------------- | ||
| bool | ||
| GetIdentifierInfo(); | ||
|
|
||
| void | ||
| MaybeLogStateChange (lldb::StateType new_state); | ||
|
|
||
| NativeProcessDarwinSP | ||
| GetNativeProcessDarwinSP(); | ||
|
|
||
| void | ||
| SetStopped(); | ||
|
|
||
| inline void | ||
| MaybePrepareSingleStepWorkaround(); | ||
|
|
||
| inline void | ||
| MaybeCleanupSingleStepWorkaround(); | ||
|
|
||
| // ----------------------------------------------------------------- | ||
| // Member Variables | ||
| // ----------------------------------------------------------------- | ||
|
|
||
| // 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; | ||
|
|
||
| struct proc_threadinfo m_proc_threadinfo; | ||
|
|
||
| thread_identifier_info_data_t m_ident_info; | ||
|
|
||
| #if 0 | ||
| lldb::StateType m_state; | ||
| ThreadStopInfo m_stop_info; | ||
| NativeRegisterContextSP m_reg_context_sp; | ||
| std::string m_stop_description; | ||
| using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>; | ||
| WatchpointIndexMap m_watchpoint_index_map; | ||
| // cpu_set_t m_original_cpu_set; // For single-step workaround. | ||
| #endif | ||
| }; | ||
|
|
||
| typedef std::shared_ptr<NativeThreadDarwin> NativeThreadDarwinSP; | ||
|
|
||
| } // namespace process_darwin | ||
| } // namespace lldb_private | ||
|
|
||
| #endif // #ifndef NativeThreadDarwin_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| //===-- NativeThreadListDarwin.h --------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Created by Greg Clayton on 6/19/07. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef __NativeThreadListDarwin_h__ | ||
| #define __NativeThreadListDarwin_h__ | ||
|
|
||
| #include <memory> | ||
| #include <mutex> | ||
| #include <vector> | ||
|
|
||
| #include "lldb/lldb-private-forward.h" | ||
| #include "lldb/lldb-types.h" | ||
|
|
||
| #include "MachException.h" | ||
|
|
||
| // #include "ThreadInfo.h" | ||
|
|
||
| namespace lldb_private { | ||
| namespace process_darwin { | ||
|
|
||
| class NativeBreakpointDarwin; | ||
| class NativeProcessDarwin; | ||
|
|
||
| class NativeThreadDarwin; | ||
| using NativeThreadDarwinSP = std::shared_ptr<NativeThreadDarwin>; | ||
|
|
||
| class NativeThreadListDarwin | ||
| { | ||
| public: | ||
| NativeThreadListDarwin(); | ||
| ~NativeThreadListDarwin(); | ||
|
|
||
| void | ||
| Clear(); | ||
|
|
||
| void | ||
| Dump(Stream &stream) const; | ||
|
|
||
| // 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; | ||
| nub_size_t GetRegisterContext (nub_thread_t tid, void *buf, size_t buf_len); | ||
| nub_size_t SetRegisterContext (nub_thread_t tid, const void *buf, size_t buf_len); | ||
| uint32_t SaveRegisterState (nub_thread_t tid); | ||
| bool RestoreRegisterState (nub_thread_t tid, uint32_t save_id); | ||
| #endif | ||
|
|
||
| const char * | ||
| GetThreadInfo(lldb::tid_t tid) const; | ||
|
|
||
| void | ||
| ProcessWillResume(NativeProcessDarwin &process, | ||
| const ResumeActionList &thread_actions); | ||
|
|
||
| uint32_t | ||
| ProcessDidStop(NativeProcessDarwin &process); | ||
|
|
||
| bool | ||
| NotifyException(MachException::Data& exc); | ||
|
|
||
| bool | ||
| ShouldStop(bool &step_more); | ||
|
|
||
| // 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. | ||
| #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); | ||
| nub_addr_t GetDispatchQueueT (nub_thread_t tid); | ||
| nub_addr_t GetTSDAddressForThread (nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size); | ||
| #endif | ||
|
|
||
| // 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; | ||
|
|
||
| lldb::tid_t | ||
| ThreadIDAtIndex(size_t idx) const; | ||
|
|
||
| lldb::tid_t | ||
| GetCurrentThreadID(); | ||
|
|
||
| NativeThreadDarwinSP | ||
| GetCurrentThread(); | ||
|
|
||
| void | ||
| NotifyBreakpointChanged(const NativeBreakpointDarwin *bp); | ||
|
|
||
| uint32_t | ||
| EnableHardwareBreakpoint(const NativeBreakpointDarwin *bp) const; | ||
|
|
||
| bool | ||
| DisableHardwareBreakpoint(const NativeBreakpointDarwin *bp) const; | ||
|
|
||
| uint32_t | ||
| EnableHardwareWatchpoint(const NativeBreakpointDarwin *wp) const; | ||
|
|
||
| bool | ||
| DisableHardwareWatchpoint(const NativeBreakpointDarwin *wp) const; | ||
|
|
||
| uint32_t | ||
| GetNumberOfSupportedHardwareWatchpoints() const; | ||
|
|
||
| size_t | ||
| GetThreadIndexForThreadStoppedWithSignal(const int signo) const; | ||
|
|
||
| NativeThreadDarwinSP | ||
| GetThreadByID(lldb::tid_t tid) const; | ||
|
|
||
| NativeThreadDarwinSP | ||
| GetThreadByMachPortNumber(::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; | ||
|
|
||
| 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; | ||
| }; | ||
|
|
||
| } // namespace process_darwin | ||
| } // namespace lldb_private | ||
|
|
||
| #endif // #ifndef __NativeThreadListDarwin_h__ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| <plist version="1.0"> | ||
| <dict> | ||
| <key>CFBundleDevelopmentRegion</key> | ||
| <string>English</string> | ||
| <key>CFBundleIdentifier</key> | ||
| <string>com.apple.lldb-server</string> | ||
| <key>CFBundleInfoDictionaryVersion</key> | ||
| <string>6.0</string> | ||
| <key>CFBundleName</key> | ||
| <string>lldb-server</string> | ||
| <key>CFBundleVersion</key> | ||
| <string>2</string> | ||
| <key>SecTaskAccess</key> | ||
| <array> | ||
| <string>allowed</string> | ||
| <string>debug</string> | ||
| </array> | ||
| </dict> | ||
| </plist> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| <plist version="1.0"> | ||
| <dict> | ||
| <key>com.apple.springboard.debugapplications</key> | ||
| <true/> | ||
| <key>com.apple.backboardd.launchapplications</key> | ||
| <true/> | ||
| <key>com.apple.backboardd.debugapplications</key> | ||
| <true/> | ||
| <key>com.apple.frontboard.launchapplications</key> | ||
| <true/> | ||
| <key>com.apple.frontboard.debugapplications</key> | ||
| <true/> | ||
| <key>run-unsigned-code</key> | ||
| <true/> | ||
| <key>seatbelt-profiles</key> | ||
| <array> | ||
| <string>debugserver</string> | ||
| </array> | ||
| <key>com.apple.diagnosticd.diagnostic</key> | ||
| <true/> | ||
| <key>com.apple.security.network.server</key> | ||
| <true/> | ||
| <key>com.apple.security.network.client</key> | ||
| <true/> | ||
| </dict> | ||
| </plist> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| <plist version="1.0"> | ||
| <dict> | ||
| <key>com.apple.diagnosticd.diagnostic</key> | ||
| <true/> | ||
| </dict> | ||
| </plist> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| /* | ||
| * nub.defs | ||
| */ | ||
|
|
||
| #import <mach/mach_exc.defs> |